当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);
}
我认为我不会增加,因为sz不是VLA但j会增加,因为arr是VLA 但是在输出中,i和j都没有增加。
答案 0 :(得分:4)
引用my answer to another question:
“转换”是由减法运算符引起的。您可以使用逗号运算符查看类似的,也许更令人惊讶的结果:
printf("%zu\n", sizeof(1, a));
也会打印
sizeof(int *)
,因为逗号运算符会导致在值上下文中使用。
基本上,由于逗号运算符,the type of arr
是一个指针,并且VLA的大小不会出现在图片中。有关详细信息,请参阅我的链接答案。
答案 1 :(得分:2)
没有太多解释,但我怀疑它是逗号运算符的一些编译器优化。逗号操作的值是最后一个表达式的值。由于编译器知道sizeof是一元运算符并且使用逗号运算,因此除了最后一个表达式之外,它不会评估任何表达式(无论最后一个是否是对VLA的引用)。
我写了一些测试程序(Ubuntu 9.04上的gcc 4.3.3):
$ cat test.c #with sizeof
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
sizeof( printf("%s%d\n", "comma!", ++x), x));
}
$ gcc -S test.c
$ cat test.s
.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
请注意缺少字符串文字和第二次printf()
调用。
$ cat test-alt.c#without sizeof
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
( printf("%s%d\n", "comma!", ++x), x));
}
$ gcc -S test-alt.c
$ cat test-alt.s
.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
可能会在某处记录,但我不知道在哪里看。
答案 2 :(得分:1)
sizeof在编译时进行评估。在C99中,对于可变长度数组,它将等到运行时。检查this answer是否有类似的问题。
答案 3 :(得分:0)
编译器知道数组大小:显然是20.我不认为sz是VLA。尝试使用数组大小作为函数参数,用于eaxmple:
void Function(int size) { int arr[size]; ... }BTW,要了解会发生什么,建议阅读编译器生成的汇编代码。检查sizeof是否已在编译时替换为常量。