数组的有趣现象

 
 1 #include <stdio.h>
 2 #include <stdlib.h> 
 3  
 4 
 5 int main()
 6 { 
 7     int a[5];
 8 
 9     printf("sizeof(a) = %d\n", sizeof(a)); 
10     printf("sizeof(a[0]) = %d\n", sizeof(a[0])); 
11     printf("sizeof(&a) = %d\n", sizeof(&a));
12     printf("sizeof(&a[0])= %d\n", sizeof(&a[0]));
13     return 0;
14 }
15 /** 运行结果
16   sizeof(a) = 20
17 sizeof(a[0]) = 4
18 sizeof(&a) = 4
19 sizeof(&a[0])= 4
20  */

分析:

  • 第9行: a是数组的名称,sizeof(a)是求数组长度(数组占用内存几个字节):5 * sizeof(int) = 20;所以计算结果为20
  • 第10行:a[0]是数组的第一个元素,sizeof(a[0])是对元素大小进行计算(元素占用内存几个字节),win32下int数据类型点4个字节,所以计算结果为4
  • 第11行:&a是数组a的首地址,但是sizeof(&a)是对地址大小进行计算,在32位系统下,地址和指针一样都是占4个字节,所以计算结果为4
  • 第12行:&a[0]是数组a的第一个元素a[0]的地址,sizeof(&a[0])是对a[0]地址大小进行计算,在32位系统下,地址和指针一样都是占4个字节,所以计算结果为4
  • &a[0]与&a的区别:虽然sizeof(&a)与sizeof(&a[0])计算结果一样,但意义不同,&a[0]是数组元素a[0]的地址,&a是数组a的首地址.
printf("sizeof(a[10]) = %d\n", sizeof(a[10]));
//sizeof(a[10]) = 4

注意,上面这个printf打印语句可以正常运行,加为关键字sizeof(它是一个关键字,而不是个函数)求值是在编译的时候,虽然并不存在a[10]这个元素,但是这是也没有去真正访问a[10]这个元素,而是仅仅根据数组元素的类型来确定其值。所以编译器并没有报错。

2. 数组名a作为左值和右值的区别

首先,数组名a是不能作为左值的(a[i]可以作为在左值)。

a作为右值时,它并不是代表数组的首地址,而是与&a[0]意义一样,都是表示数组首元素的地址,因此对a+1等价于&a[1];

1 int main()
2 { 
3     int a[5];
4     
5     *(a+1) = 5;
6     printf("a[1] = %d\n", a[1]);
7     return 0;
8 }

3. a 与 &a 的区别

 

 1 int main()
 2 { 
 3     int i, j;
 4     int a[5] = {1,2,3,4,5};
 5 
 6     i = *(a+1); 
 7     int *ptr = (int *)(&a+1);
 8     j = *(ptr-1);
 9     printf("*(a+1) = %d,\t*(ptr-1) = %d\n", i, j);
10     
11     return 0;
12 }

知识点:对指针进行加1的操作,得到的是下一个元素的地址,而不是在原有的地址值直接加1。所以一个类型为T的指针的移动,以sizeof(T)为移动单位.

分析:

  • 第6行:前面说过数组名a作为右值时,代表的是数组首元素的地址(等价于&a[0]),所以a+1为&a[1],*(a+1) = a[1],所以输出的是2
  • 第7行:&a的值是数组的首地址(0x0016fd54),所以&a+1是下一个数组的地址(0x0016fd68, 计算方法:0x0016fd54+5*4(5*4化作十六进制0x00000014) = 0x0016fd68),ptr指针指向的是&a[4](0x0016fd64)地址后面的那个地址(0x0016fd68),(ptr - 1)指向的是a[4](0x0016fd64),所以输出的是5.
  • 各地址如下(vc2010的一次运行情况):
  • +  &a+1     0x0016fd68     int [5]*
    +  ptr         0x0016fd68     int *
    +  ptr-1      0x0016fd64     int *
      *(ptr-1)    5                    int
      *(a+1)     2                     int
    +  a           0x0016fd54    int [5]

      

 

本文大部分摘自《C语言深度剖析》

 

 

 

 

 

 

posted @ 2012-08-11 15:12  blankqdb  阅读(187)  评论(0)    收藏  举报