sizeof如何知道数组的大小?

19

我有以下代码:

main() {
    int array[5] = {3,6,9,-8,1};
    printf("the size of the array is %d\n", sizeof(array));
    printf("the address of array is %p\n", array);
    printf("the address of array is %p\n", &array);
    int * x = array;
    printf("the address of x is %p\n", x);
    printf("the size of x is %d\n", sizeof(x));
}

输出结果为

the size of the array is 20
the address of array is 0x7fff02309560
the address of array is 0x7fff02309560
the address of x is 0x7fff02309560
the size of x is 8

我知道变量array会被视为指向数组第一个元素的指针,因此我理解x的大小为8。但我不知道数组的大小为什么是20。在64位机器上不应该是8吗?

另外程序如何知道它的大小是20呢?据我所知,在C语言中它不存储元素的数量。为什么sizeof(array)sizeof(x)不同?我查阅了关于数组衰减的帖子,但对这个问题没有头绪。


7
编译器知道数组元素的大小和数组中有多少元素,因此它可以将这两个数相乘以得出 sizeof 的结果。这是编译器的工作,需要它来完成。 - Jonathan Leffler
7
数组不是指向其第一个元素的指针——有时它只是自动转换为指针。 - user253751
3
你可能忽略了一个关键点:尽管它的外观类似,但 sizeof 不是一个函数,而是一个编译时运算符。只有编译器需要知道答案,因此信息不被“存储”在程序中也没有关系。 - Euro Micelli
@Mehrdad 变长数组在这个主题中有什么区别吗? - Marcus Thornton
@Mehrdad,这个问题的重复是哪一个? - Marcus Thornton
显示剩余3条评论
7个回答

21
在大多数情况下,数组的名称会退化为指向数组第一个元素的指针。然而,有两个例外。最重要的是当数组名用作sizeof操作符或address-of操作符(&)的操作数时,数组名仍然是整个数组的标识符。
对于非VLA数组,这意味着可以在编译时静态地确定数组的大小,并且表达式的结果将是数组的大小(以字节为单位),而不是指针的大小。
当您获取数组的地址时,您将获得与未获取地址的数组名称相同的值(即相同的地址)。但类型是不同的 - 当您明确获取地址时,您得到的是指向"N个T类型项的数组"的指针。这意味着(例如),虽然array+1指向数组的第二个元素,但&array+1指向整个数组结束后的另一个数组。
假设有至少两个项的数组,*(array+1)将引用数组的第二个元素。无论数组大小如何,&array+1都将产生超出数组末尾的地址,因此尝试对该地址进行解引用会导致未定义的行为。
在您的情况下,假设数组大小为20,数组中一个元素的大小为4,如果array为0x1000,则array+1将为0x1004,而&array+1将为0x1014(0x14 = 20)。

15
您的数组长度是静态的,因此可以在编译时确定。您的编译器知道 sizeof(int) = 4 和您的静态数组长度[5]。4 * 5 = 20
编辑:您的编译器int可能是32位,但寻址为64位。这就是为什么sizeof(pointer)返回8的原因。

11
请注意,sizeof不是一个库函数。 sizeof是一个编译时一元运算符[...],可用于计算任何对象的大小。因此,sizeof并不知道数组的大小,编译器才知道数组的大小,并且按定义,当应用于数组时,结果是数组中总字节数的数量。

7

指针和数组是两种不同的数据类型。

数组可以容纳相似的数据类型元素。数组的内存是连续的。

指针用于指向一些有效的内存位置。

sizeof(type)会给出你传递的类型所占用的字节数。

现在,如果你传递一个数组,编译器就知道这是一个数组以及其中的元素数量,并将这么多元素乘以相应的数据类型大小值。

在这种情况下:

5*4 = 20

再次强调,sizeof(int) 或者 sizeof(pointer) 取决于平台。在这种情况下,你看到的是 sizeof(pointer) 为8。


4
不,数组作为 sizeof 运算符的操作数时不会退化。这是数组不退化的为数不多的情况之一。如果在您的机器上 int 是 4 字节,则数组的总字节数应为 20(4 * 5)。我们甚至不需要一个对象来测试这个。
sizeof(int[5]) // 20
sizeof(int*)   // 8 on a 64-bit machine

2

C11: 6.5.3.4 (p2)

sizeof 运算符返回其操作数的大小(以字节为单位),其操作数可以是一个表达式或类型的括号名称。 大小由操作数的类型确定。[...]

在声明中:

int array[5]  
< p > array 的类型是一个包含5个 int 元素的数组。编译器会根据这个类型确定 array 的大小。


0

试试这个

int x = sizeof(array)/sizeof(int);
printf("the size of the array is %d\n", x);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接