C sizeof运算符中操作数的求值

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; 国际航空公司

当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;
国际航空公司[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