看看C代码。
#include <stdio.h>
int main(void)
{
int v[3] = {1, 2, 3};
printf("%d\n", v);
printf("%d\n", v + 0);
printf("%zu\n", sizeof(v));
printf("%zu\n", sizeof(v + 0));
printf("%zu\n", sizeof(v + 1));
printf("%zu\n", sizeof(v + 2));
return 0;
}
这是其中一个输出:
-587904464
-587904464
12
8
8
8
我认为v与v + 0相同。
两者都是指向数组v [3]中第一个元素的指针。
因此,v和v + 0具有相同的值。
但为什么他们不能保持相同的字节? (sizeof(v)和sizeof(v + 0)不同)
在大多数情况下,数组标识符衰减到指向数组第一个元素的指针。但是,当数组是sizeof
运算符的操作数时,不会发生此转换,并且运算符会以字节为单位生成数组的大小。 From §6.3.2.1 ¶3 of the C11 Draft Standard:
除非它是sizeof运算符,_Alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则将具有类型''数组类型''的表达式转换为表达式输入''指向类型'的指针,指向数组对象的初始元素,而不是左值。
请注意,在C18标准中,_Alignof
算子已被删除(discussion here)。
因此,sizeof(v)
以字节为单位生成数组v[]
的大小,即12个字节。也就是说,操作数的类型是int [3]
,因为数组尚未转换为指向int
的指针(就像在大多数表达式中一样),并且sizeof
运算符产生这种类型的大小(3个int
s的数组)字节。
但是使用sizeof (v + 0)
,表达式v + 0
的类型决定了sizeof
算子产生的结果。在表达式v + 0
中,数组v[]
衰减到指向v[]
的第一个元素的指针,然后根据指针算法的规则添加0
。结果是指向int
的指针(因为&v[0]
本身是指向int
的指针),因此表达式v + 0
的类型是int *
。因此,在这种情况下,sizeof
运算符产生指向int
的指针的大小。同样适用于类似的表达式sizeof (v + 1)
等。
另外,请注意,在首次转换为%p
之后,必须使用void *
转换说明符打印地址,以避免未定义的行为:
printf("%p\n", (void *)v);
printf("%p\n", (void *)(v + 0));