C sizeof运算符中操作数的求值
当sizeof运算符计算操作数是否为VLA时,我尝试将其测试为:C sizeof运算符中操作数的求值,c,sizeof,C,Sizeof,当sizeof运算符计算操作数是否为VLA时,我尝试将其测试为: #include<stdio.h> int main(void) { int sz=20,i=0,j=0; int arr[sz]; printf("%d\n",sizeof((++i,sz))); printf("%d\n",sizeof((++j,arr))); printf("%d\n%d\n",i,j); } #包括 内部主(空) { intsz=20,i=0,j=0; 国际航空公司
#include<stdio.h>
int main(void)
{
int sz=20,i=0,j=0;
int arr[sz];
printf("%d\n",sizeof((++i,sz)));
printf("%d\n",sizeof((++j,arr)));
printf("%d\n%d\n",i,j);
}
#包括
内部主(空)
{
intsz=20,i=0,j=0;
国际航空公司[sz];
printf(“%d\n”,sizeof(++i,sz));
printf(“%d\n”,sizeof(++j,arr));
printf(“%d\n%d\n”,i,j);
}
我想我不会因为sz不是VLA而增加,但是j会因为arr是VLA而增加。但是在输出中,i和j都没有增加。编译器知道数组大小:它显然是20。我不认为sz是VLA。尝试使用数组大小作为函数参数,例如: void Function(int size) { int arr[size]; ... } 空函数(整数大小) { int arr[尺寸]; ... }
顺便说一句,为了理解发生了什么,建议阅读编译器生成的汇编代码。检查sizeof是否已在编译时被常量替换。sizeof在编译时求值。在C99中,对于可变长度数组,它将等待运行时。检查类似问题。引用: “转换”是由于减法运算符引起的。使用逗号运算符,您可以看到类似的、也许更令人惊讶的结果:
printf("%zu\n", sizeof(1, a));
还将打印sizeof(int*)
,因为逗号运算符导致在值上下文中使用
基本上,由于逗号运算符,
arr
是一个指针,VLA的大小不会出现在图片中。有关详细信息,请参阅我的链接答案。没有太多解释,但我怀疑这是对逗号运算符的一些编译器优化。逗号运算的值是最后一个表达式的值。由于编译器知道sizeof是一元运算符,并且提供了逗号操作,因此除了最后一个表达式之外,它不必计算任何表达式(不管最后一个表达式是否是对VLA的引用)
我编写了一些测试程序(Ubuntu 9.04上的GCC4.3.3):
$cat test.c#尺寸为
请注意缺少字符串文本和第二个printf()
调用
$cat test-alt.c#无尺寸
可能在某个地方被记录,但我不知道该去哪里看。
这是一个关于C而不是C++的问题。VLAs在C++中不存在。哦,其他人把它标记为C++。坏的其他人。好吧。我明白了。那么有没有一种方法可以像我在这里尝试做的那样,利用这个事实“sizeof计算操作数,如果它是vLA”来递增或修改其他操作数?@Happy:我不会称之为“利用”,它更像是“滥用sizeof
运算符”。你到底想做什么?在这种情况下,编译器确实知道数组的大小,但它在技术上是一个VLA,因为sz是一个变量,而不是一个常量。即使它是一个常量(const int sz=20;),这也不会使数组的VLA变小(因为它始终具有相同的大小)。
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
sizeof( printf("%s%d\n", "comma!", ++x), x));
}
.file "test.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $0, -8(%ebp)
movl $4, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
( printf("%s%d\n", "comma!", ++x), x));
}
.file "test-alt.c"
.section .rodata
.LC0:
.string "comma!"
.LC1:
.string "%s%d\n"
.LC2:
.string "%d\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $0, -8(%ebp)
addl $1, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, 8(%esp)
movl $.LC0, 4(%esp)
movl $.LC1, (%esp)
call printf
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC2, (%esp)
call printf
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits