sizeof(数组名):如 sizeof(a),数组名表示整个数组,所以计算的是整个数组的大小。

sizeof(&数组名):如 sizeof(&a),取出的是整个数组的地址,所以计算的是地址大小。

除上述两种情况外,其它所有形式的数组名都是指该形式的数组名的首元素的地址。

需要注意的是:

在C/C++中数组会退化为指针,所以数组名即为首元素地址,&a的值和a的数值是相同的(可以输出观察一下),但是类型和意义不同,地址偏移量也不同

例如int a[10];

a相当于int*,a+1相当于a+1*sizeof(int),即偏移一个元素的长度

&a相当于int**,即指向数组的指针,&a+1相当于&a+sizeof(a),即偏移一个数组的长度

下面通过一系列例子展现用sizeof计算数组相关大小

int a[3][4] = { 0 };

1. printf("%d\n", sizeof(a));

// 3*4*4=48,三行四列共12个元素,每个元素4字节.

2. printf("%d\n", sizeof(* a));

// 16, 由于a前有*,所以a没有单独放在sizeof中,也没有单独取地址放在sizeof中,所以表示首元素地址也就是第一行地址,*a解引用表示第一行元素,第一行4*4=16字节。此处也可以写成*(a + 0).

3. printf("%d\n", sizeof(a + 1));

// 4, 二维数组的首元素地址为第一行的地址,a + 1表示第二行的地址,地址大小为4.

4. printf("%d\n", sizeof(* (a + 1)));

// 16,  a + 1表示第二行的地址,* (a + 1)解引用后表示第二行元素,整个第二行4*4=16字节.

5. printf("%d\n", sizeof(a[0]));

// 16, a[0]作为数组名单独放在sizeof内部,表示第一行的数组名,整个第一行为4*4=16字节.

6. printf("%d\n", sizeof(a[0] + 1));

// 4, a[0]作为数组名并没有单独放在sizeof内部,表示第一行的第一个元素的地址,a[0] + 1表示第二个元素的地址,地址大小为4.

7. printf("%d\n", sizeof(* (a[0] + 1)));

// 4, a[0] + 1表示第一行第二个元素的地址,(* (a[0] + 1)解引用后表示第一行第二个元素,int占4个字节.

8. printf("%d\n", sizeof(a[0][0]));

// 4, 第一行第一个元素4字节.

9. printf("%d\n", sizeof(&a[0] + 1));

// 4, &a[0]表示第一行的地址,&a[0] + 1表示第二行的地址,与第3题效果一致.

10. printf("%d\n", sizeof(* (&a[0] + 1)));

// 16, &a[0] + 1表示第二行的地址,* (&a[0] + 1)解引用后表示第二行元素,整个第二行为4*4=16字节,与第4题效果一致.

11. printf("%d\n", sizeof(a[3]));

// 16, a[3]其实是第4行的数组名(如果存在的话),sizeof不会去真的访问第4行,但是它知道第4行的类型属性为int[4].

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐