Sizeof运算符是编译时运算符。在编译期间使用常量结果值转换sizeof表达式。 [异常可变参数模板c99]
通常,编译器会在编译时修复变量的大小。数组n的 。 但是,当我打印sizeof数组时,它给出了正确的大小? 这个代码是否在编译时为n?
分配内存如何评估sizeof?
数组a []在函数中怎么样?
int fun(int n)
{
char a[n+3];
return sizeof(a);
}
int
main( )
{
int i;
while(i!=-1){
scanf("%d",&i);
int n[i];
printf("\nsize: %d %d\n",fun(3),sizeof n);
}
}
当我尝试这个: sizeof正确打印n的大小[(sizeof(int))* i]但函数总是给出错误的结果6?
如何实现sizeof并计算大小(对于float,int,...数据类型,变量,数组......)?
感谢任何代码!
答案 0 :(得分:10)
正如您所提到的,sizeof
计算通常由编译器在编译时进行。这并不总是正确的(例如,C99 / C11可变长度数组),但它是一个合理的近似值。
由于编译器知道(或决定)每种类型的大小,它只能在编译期间进行简单的常量替换。
对于您的示例,a
和n
都是可变长度数组,并且sizeof
运算符在运行时应用。
从C11开始,第6.5.3.4节sizeof
和_Alignof
运算符,第2段:
sizeof
运算符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的带括号的名称。大小由操作数的类型确定。结果是整数。如果操作数的类型是可变长度数组类型,则计算操作数;否则,不评估操作数,结果是整数常量。
编辑说明:sizeof
返回size_t
,而不是int
,因此您应使用%zu
格式说明符而不是%d
。如果打开相应的标志,编译器可能会发出警告。
答案 1 :(得分:1)
维基百科很好地解释了sizeof
的实施,详见here。
编译器有责任为每个目标平台正确实现sizeof运算符。在许多情况下,将为该平台提供官方应用程序二进制接口(ABI)文档,指定编译器必须符合的数据类型的格式,填充和对齐。在大多数情况下,sizeof是一个编译时运算符,这意味着在编译期间,sizeof表达式将被常量结果值替换。但是,应用于C99中引入的可变长度数组的sizeof需要在程序执行期间进行计算。
答案 2 :(得分:0)
当sizeof
的操作数不是可变长度数组(VLA)时,它sizeof
并不真正“计算”任何东西。结果立即为编译器所知为编译时常量。在编译期间,该常量代替sizeof
。
如果操作数是VLA,则编译器只生成从VLA本身检索大小信息的代码。所以,是的,在一般情况下,典型的实现确实将VLA的大小存储在VLA本身内。在您的示例中,这意味着分配给a
的内存也将包含存储n + 3
值的位置。
当然,编译器可以在明显的情况下优化此评估,甚至在最明显的情况下用编译时常量替换它。在您的示例中,编译器可能足够聪明,不能从数组a
中检索大小,而是立即意识到大小等于n + 3
。