我们知道,当我们使用数组时,它保存第一个元素的地址,而&array是存储整个数组的地址,当我在printf中使用它时为true,但是在sizeof运算符中,这是相反的行为,为什么
我正在Windows 7上使用带有GCC的代码块
int main(void)
{
int c[5];
printf(" %d %d %d %d\n",c,c+1,&c,&c+1);\\when we add 1 in "c" it add more 4 bytes and when "&c+1" it add 20 byte witch is true
printf(" %u %u ",sizeof(c),sizeof(&c));\\But when we print first element size (with "c") it give 20 byte and when print (With "&c") whole arry size it give 4 byte
return 0;
}
\我不明白为什么要解释
答案 0 :(得分:6)
我认为您需要了解的是,&array
仍然是一个指针,只是类型不同。
对于int arr[]={4,3,2,1,0}
arr
与&arr[0]
相同,即int *
,但是对于sizeof
运算符,它的行为有所不同(请参见下面的注释)。当传递给sizeof
运算符时,它将为您提供整个数组的大小,在这种情况下为sizeof(int [4])
。&arr
的类型为int (*)[4]
,它是一个指针。因此,要获取数组中的元素数量,您应该执行类似的操作
printf ("Number of elements = %zu", sizeof(arr)/sizeof(arr[0]));
/ *(size of the entire array / size of one element in the array) */
引用C11
,第6.3.2.1章(强调我的)
除非它是
sizeof
运算符,_Alignof
运算符或 一元&
运算符,或者是用于初始化数组的字符串文字,该表达式具有 类型“类型数组” 转换为类型为“类型指针” 的表达式 数组对象的初始元素,不是左值。 [...]
说,
sizeof
产生类型为size_t
的结果,您应该使用%zu
格式说明符来打印结果。%p
格式说明符并将相应的参数强制转换为void *
。答案 1 :(得分:4)
首先,如果要打印sizeof
的结果,则正确的格式为%zu
。 sizeof
给您size_t
,而不是int
。要打印指针,请使用%p
并将参数强制转换为(void *)
。
第二,要获得数组中元素的数量,为sizeof arr / sizeof arr[0]
(整个数组的大小除以单个元素的大小,也可以写为sizeof arr / sizeof *arr
)。
也就是说,您要询问的内容确实与数组无关。例如,如果您这样做
char c;
然后sizeof &c
将为4(在32位平台上),但是&c + 1
将为您提供比&c
高1字节而不是4字节的内存地址。>
这是因为指针算术是以指向类型(而不是指针本身的类型)为单位进行的。也就是说,您需要比较ptr + 1
和sizeof *ptr
(或&var + 1
和sizeof var
)。
在您的代码中,四个表达式中的三个很简单:
sizeof &arr
为4,因为&arr
的类型为“指向5个整数的数组的指针”,并且您使用的是32位平台,因此指针为4个字节。sizeof arr
为20,因为arr
的类型为“ 5个整数的数组”,而int
的大小为4字节,因此该数组占用5 * 4 = 20字节。&arr + 1
为您提供一个arr
后的内存地址。这就像问“ arr
是否是数组的元素,下一个元素将从何处开始?”。由于arr
的大小为20个字节,因此arr
前一个的内存地址将增加20个字节。剩下奇怪的了:
arr + 1
会编译,因为arr
会在此处衰减为指针。也就是说,由于数组不是sizeof
或&
的操作数,因此它求值为指向第一个元素的指针,如&arr[0]
。并且在&arr[0] + 1
中,指向的类型为int
,因此添加1
意味着步进到内存中下一个int
,相距4个字节。