C 具有随机长度的数组的sizeof()

C 具有随机长度的数组的sizeof(),c,gcc,random,sizeof,C,Gcc,Random,Sizeof,您能解释一下sizeof()如何处理随机长度数组吗?我认为在编译过程中会计算数组的sizeof(),但是,具有随机长度的数组的大小似乎计算正确 例如: #include <stdlib.h> #include <stdio.h> #include <time.h> int main(){ srand ( (unsigned)time ( NULL ) ); int r = rand()%10; int arr[r]; //array

您能解释一下
sizeof()
如何处理随机长度数组吗?我认为在编译过程中会计算数组的
sizeof()
,但是,具有随机长度的数组的大小似乎计算正确

例如:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(){
    srand ( (unsigned)time ( NULL ) );
    int r = rand()%10;
    int arr[r]; //array with random length
    printf("r = %d size = %d\n",r, sizeof(arr)); //print the random number, array size
    return 0;
}

编译器:gcc 4.4.3

在C99中,编译器足够聪明,知道在运行时调用
rand()

在C99中,可变大小数组的大小是在运行时计算的。从C99草案6.5.3.4/2中:

sizeof运算符生成其操作数的大小(以字节为单位),该操作数 可以是表达式或类型的括号名称。尺寸是 根据操作数的类型确定。结果是一个整数如果 操作数的类型是可变长度数组类型,即操作数 被评估;否则,将不计算操作数并返回结果 是一个整数常量


当将
sizeof
与C99中引入的VLAs(可变长度数组)一起使用时,它们的大小是在运行时而不是编译时计算的


在你的代码中,可以看到关于这个主题的非常好的参考资料,
arr
是一种特殊的数组:它是一种VLA(可变长度数组)

标准(6.5.3.4)中sizeof的段落表示

如果操作数的类型是可变长度数组类型,则对操作数求值


所以它不是编译时常量

我不知道如何
intarr[r]编译。我认为在编译过程中,堆栈中的数组需要知道它们的大小。@orip:查看C99的可变长度数组查看:注意,如果
rand()%10
恰好为0,则行为未定义。C不支持零大小的数组(尽管gcc可以作为一个扩展)。。。使数组特别的不是
rand()
。这段代码:
intk=42;int-arr[k];arr的大小
有一个和OP一样特殊的数组。@pmg:我没有跟踪你。rand()似乎生成了一个随机数,用于数组大小。是的,但是
sizeof
操作符“起作用”,因为有两个原因:数组是VLA,编译器是C99兼容的。用C89编译器试试这个:
constintk=42;int-arr[k];arr的大小@代码猴子:是的。这两种情况的共同点是,数组长度是在运行时计算的,至少在原则上是这样。您能向我解释更多细节吗?关于这个问题和您的答案,我不太了解。别跟我发疯。这里的要点是,在C99中,数组的大小不必在编译时指定。在这种情况下,sizeof不是在编译时计算的,而是在运行时计算的。这是否意味着数组的内存占用可能是数组大小加上存储其大小的额外字节数?@zoli2k:否。数组的大小(或者更可能是元素数)将存储在内存中的某个位置,但这不计入数组大小
sizeof arr
是元素数乘以每个元素的大小。@R..:你说得对。大小必须以某种方式可访问,但如果从未使用过,则可以对其进行优化,如果可以在编译时计算(即使它不是常量表达式),则即使使用了它,也不需要将其存储在任何位置。问题是编译器可能会生成额外的数据,可能会占用内存,但这并不计入arr的大小。一位语言律师打趣道:C标准的这一部分实际上有点措词不当。它表示在表达式
sizeof arr
中,表达式
arr
是经过计算的,但不清楚这是什么意思
arr
是数组类型的表达式;其值由其元素的值组成。(在这种情况下,指针通常不会衰减。)但是
sizeof arr
当然不需要计算数组本身,它只需要确定它有多大,信息来自类型,而不是值。但我不知道该怎么说。@Keith,我只是想大声说出来,但是如果我有
sizeof(arrpar[++I])
,其中
arrpar
类似于
int(*int[6])[t]
。在这种情况下,计算表达式会产生一个副作用,即递增
i
,或者如果表达式是空指针,则调用未定义的行为(通常是segfault)。我刚试过这个。在这种情况下,CLANG不会增加
i
,但GCC 4.1.2不会。CLANG或者没有费心执行取消引用,或者它被优化掉了(完全合法,因为只有空指针才重要,取消引用是未定义的行为,因此什么都不做是合法的)。仔细看,我看到CLANG确实执行了取消引用,但它被优化掉了。我还应该澄清,任何无效指针都很重要,不仅仅是空指针,编译器在这种情况下可能仍然什么也不做。
r = 8 size = 32
r = 6 size = 24
r = 1 size = 4