第29课 指针和数组分析(下)

1. 数组的访问方式

(1)以下标的形式访问数组中的元素:如a[i];

(2)以指针的形式访问数组中的元素:如*(a+i)

2. 下标形式 VS 指针形式

(1)指针形式以固定增量在数组中移动时,效率高于下标形式

(2)指针增量为1且硬件具有硬件增量模型时,效率更高

(3)下标形式与指针形式的转换:a[n]==*(a+n)==*(n+a)==n[a];

▲注意:

①现代编译器的生成代码优化率已大大提高,在固定增量时,下标形式的效率与指针形式相当;

②但从可读性和代码维护的角度看,下标形式更优

【实例分析】数组的访问方式

#include <stdio.h>

int main(){

    int a[5] = {0};
    int* p = a;
    int i = 0;

    for(i=0; i<5; i++)
    {
       p[i] = i + 1; //利用指针给数组元素赋值
    }

    for(i=0; i<5; i++)
    {
       //以指针形式来访问数组元素
       printf("a[%d] = %d\n",i,*(a+i));
    }

    for(i=0; i<5; i++)
    {
       //以下标形式来访问数组元素
       i[a] = i + 10; //比较另类,相当于a[i] = i + 10
    }

    for(i=0; i<5; i++)
    {
       //通过指针来访问数组元素
       printf("p[%d] = %d\n",i,p[i]);
    }

    return 0;
}

【编程实验】数组和指针不同

//ext.c

//实验时,本文件应为.c,而不能是头文件。因为头文件会被直接包含在相应文件中,
//而.c文件是分别编译的

int a[5] = {1, 2, 3, 4, 5}; //在该文件中,a被看作一个数组

//29-2.c

#include <stdio.h>

//命令行编译这两个文件:gcc 29-2.c ext.c

int main(){

   //外部文件中a被定义成一个数组。int a[5] = {1, 2, 3, 4, 5}; 

    //实验1:
    extern int a[]; //本文件,如果这样声明,a仍被看作一个数组

    printf("&a = %p\n", &a); //这里的&a为整个数组的地址
    printf("a = %p\n",a);    //a为首元素的地址,数值上等于&a
    printf("*a = %d\n",*a);  //打印出第1个元素,即1

    //实验2:
/*
    extern int* a;  //如果这样声明,编译器将a当成是一个int型的
                    //指针来使用。

    printf("&a = %p\n", &a); //会从符号表中查到指针a的地址,指向数组
    printf("a = %p\n",a);    //从指针a处,取一个int型的数据,即第1个元素,为1
    printf("*a = %d\n",*a);  //试图从地址0x01处取出数据,违规内存访问错误。
*/
    return 0;
}

3. a和&a的区别

(1)a为数组首元素的地址

(2)&a为整个数组的地址,即可将数组看成是一种数据结据。如int[5];

(3)a和&a的区别在在指针运算

  a + 1 == (unsigned int)a + sizeof(*a);//a代表首元素地址,*a表示第1个元素

  &a + 1 == (unsigned int)(&a) + sizeof(*&a) ==  (unsigned int)(&a) + sizeof(a);

【实例分析】指针运算经典问题

4. 数组参数

(1)数组作为函数参数时,编译器将其编译为对应的指针。因此,一般情况下,当定义的函数中有数组参数时,需要定义另一个参数来标示数组的大小。

void f(int a[])等价于void f(int* a);

void f(int a[5])等价于void f(int* a); //就是一个指针,丢失了数组长度的信息

【实例分析】虚幻的数组参数

5. 小结

(1)数组名和指针仅使用方式相同,数组名的本质不是指针,指针的本质也不是数组。

(2)数组名并不是数组的地址,而是数组首元素的地址

(3)函数的数组参数退化指针

时间: 2024-11-14 07:34:48

第29课 指针和数组分析(下)的相关文章

第28课 指针和数组分析(上)

1. 数组的本质 (1)数组是一段连续的内存空间 (2)数组的空间大小:sizeof(array_type)*array_size; (3)数组名可看做指向数组第一个元素的常量指针 [编程实验]a + 1的结果是什么?  (答案是第2个元素的地址) #include <stdio.h> int main(){ //将数组每个元素初始化为0 int a[5] = {0}; int* p = NULL; printf("a = 0x%X\n",(unsigned int)(a)

C++ 之 第六课 指针和数组

c++语言中大部分程序都离不开指针和数组,所以,我们有必要弄清楚指针和数组. 首先定一个字符数组char s[10];然后定义一个指向字符的指针char* p;数组用[]来申明,而*则表示指针.数组是以0作为下标开始,s有10个元素,从s[0]...s[9].指针可以保存它的地址如: p = &s[1];// 这句话表示了p指向了s的第2个元素.&是取地址运算符. 那么指针到底是什么东西?为什么它会有如此大的魔力?如果你了解了汇编的基础知识.其实也不难理解?简单的解释就是它保存了一个对象的

第37课 指针阅读技巧分析

1. 指针阅读技巧:右左法则 (1)从最里层的圆括号中未定义的标示符看起 (2)首先往右看,再往左看 (3)遇到圆括号或方括号时可以确定部分类型,并调转方向 (4)重复2.3步骤,直到阅读结束 [编程实验]复杂指针的阅读 注意:当读出是数组时,须读出元素个数.元素类型         当读出是函数是,须读出参数及类型,返回值类型         当读出是指针是,须读出指针所指向的类型,有时也须读出指针的类型. 例题① int (*p)(int*, int (*f)(int*)); A.读未标示符

C语言指针与数组的定义与声明易错分析

部分摘自<C语言深度解剖> 1.定义为数组,声明为指针 在文件1中定义: char a[100]; 在文件2中声明: extern char *a; //这样是错误的 这里的extern告诉编译器a这个名字已经在别的文件中被定义了,下面的代码使用的a是在别的文件中定义的.编译器是按文件分别编译的,当a被声明为char* a时,编译器理所当然的认为a是一个指针变量,在32位系统下占用4个byte,这4个byte存放的是地址,地址指向的空间存储的是char类型数据. 程序会返回SIGSEGV. 2

第34课 多维数组和多维指针

1. 指向指针的指针 (1)指针的本质是变量,会占用一定的内存空间 (2)可以定义指针的指针来保存指针变量的地址值 (3)指针是个变量,同样也存在传值调用与传址调用 [实例分析]遍历二维数组 2. 数组名 (1)一维数组名代表数组首元素的地址:int a[5];a的类型为int* (2)二维数组名同样代表数组首元素的地址:如int a[3][5],a的类型为int(*)[5]. 二维数组 含义及类型 取地址符(&) sizeof 数组名:a ①二维数组名a指向数组首元素的地址,即第1行(a[0]

1、打印二进制机器码,程序内存分析,大端序小端序,指针数组,数组指针,数组的三种访问方式,typedef,#if-0-#endif,求数组大小,括号表达式

 1.打印二进制机器码(分别表示32位的和64位的) #include <stdio.h> /*按照8位的长度打印一个数值*/ void dis8bit(char val) { int bit = 8; while(bit--) { if(1<<bit&val){ printf("1"); } else { printf("0"); } if(!(bit%4)) printf(" "); } putchar(1

第19课 - 对象的构造(下)

第19课 - 对象的构造(下) 1. 特殊的构造函数 (1)无参构造函数 当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空. (2)拷贝构造函数 当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制. 1 #include <stdio.h> 2 3 class Test 4 { 5 private: 6 int i; 7 int j; 8 public: 9 int getI() 10 { 11 return i; 12 } 13

指针和数组解析

指针和数组 指针和数组是一样的吗? 经常可以看到“数组就是指针”.“数组名就是常量指针”这些说法,但真的是这样吗?让我们先看一下指针和数组的定义. 1. 指针 根据C99标准,指针的定义如下: A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides

指针、数组的理解与关系

一.指针的本质:变量,指针变量就是指针变量int *p:两个变量,一个p(指针变量本身)是int *类型的 另一个是*p(指针指向的那个变量)是int类型的注:指针说白了就是指针类型,前面定义的int类型是为了说明指针指向的那个数的类型,所以指针的解析方式都是按地址来解析的(不管你是char *还是double *,解析方式都是地址)而指向的那个数的类型就要看你怎么定义的了例如:int *aa是按照地址来解析的:*a则是按照int类型来解析的. (1)所有的类型的数据存储在内存中,都是按照二进制