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

数组名可以当做常量指针使用,那么指针是否也可以当做数组名来使用呢?

下标VS指针形式:

示例程序:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int a[5] = {0};
 6     int* p = a;
 7     int i = 0;
 8     
 9     for(i=0; i<5; i++)
10     {
11         p[i] = i + 1;
12     }
13     
14     for(i=0; i<5; i++)
15     {
16         printf("a[%d] = %d
", i, *(a + i));
17     }
18     
19     printf("
");
20     
21     for(i=0; i<5; i++)
22     {
23         i[a] = i + 10;
24     }
25     
26     for(i=0; i<5; i++)
27     {
28         printf("p[%d] = %d
", i, p[i]);
29     }
30     
31     return 0;
32 }

第11行将指针当做数组名来使用。

运行结果如下:

可以看到输出结果是正确的。

但是数组和指针是不同的。

示例程序:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     extern int* a;
 6     
 7     printf("&a = %p
", &a);
 8     printf("a = %p
", a);
 9     printf("*a = %d
", *a);
10 
11     
12     return 0;
13 }

ext.c文件

1 int a[] = {1, 2, 3, 4, 5};

当上述程序第5行为extern int a[];时,编译运行结果如下:

当第5行改为extern int *a;时,结果如下:

出现了段错误。

当编译ext.c的时候,在内存中出现了如下的情况,编译器在内存中分配20个字节:

  编译器编译ext.c,分配了内存,给了a一个地址0x804a014。编译器将a这个标识符映射到了0x804a014这个地址值上面。在内存中是没有变量和标识符的,只有地址。

  编译器在编译到主程序的第5行时,看到a是在外部定义的,那么就认为在外部,编译器已经给了它一个地址值了,第7行取a的地址值,自然得到了0x804a014。

  编译到第8行时,a被解释为指针,a这个变量在编译器中分配的地址为0x804a014,这个地址其实对程序员是不可见的。而a的值并不是这个地址,而是这个地址中存放的值,因此,编译器会到0x804a014这个地址里面取四个字节,这四个字节就是a的值。

   根据以上的分析,第9行就会去访问0x01这个地址的数据,因此,会出现段错误。

  可以得到结论,数组不是指针,指针也不是数组。只不过某些情况下,它们可以等价。

a和&a的区别:

指针运算经典问题:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int a[5] = {1, 2, 3, 4, 5};
 6     int* p1 = (int*)(&a + 1); 
 7     int* p2 = (int*)((int)a + 1);
 8     int* p3 = (int*)(a + 1);
 9     
10     printf("%d, %d, %d
", p1[-1], p2[0], p3[1]);
11     
12     return 0;
13 }
14 // A. 数组下标不能是负数,程序无法运行
15 // B. p1[-1]将输出随机数,p2[0]输出2, p3[1]输出3
16 // C. p1[-1]将输出乱码, p2[0]和p3[1]输出2

上面程序中给出了三种可能的答案,哪一个正确呢?

运行结果如下:

数组参数:

 当数组作为参数时,不管带不带大小,都会退化为指针。一般传数组参数时,我们会另外带一个int型参数表示数组的大小。

虚幻的数组参数示例:

 1 #include <stdio.h>
 2 
 3 void func1(char a[5])
 4 {
 5     printf("In func1: sizeof(a) = %d
", sizeof(a));
 6     
 7     *a = 'a';
 8     
 9     a = NULL;
10 }
11 
12 void func2(char b[])
13 {
14     printf("In func2: sizeof(b) = %d
", sizeof(b));
15     
16     *b = 'b';
17     
18     b = NULL;
19 }
20 
21 int main()
22 {
23     char array[10] = {0};
24     
25     func1(array);
26     
27     printf("array[0] = %c
", array[0]);
28     
29     func2(array);
30     
31     printf("array[0] = %c
", array[0]);
32     
33     return 0;
34 }

结果如下:

可见数组参数是虚幻的,会退化为指针。

int *a[10] :指针数组。数组a里存放的是10个int型指针
int (*a)[10] :数组指针,a是指针,指向一个数组。此数组有10个int型元素

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9538862.html