运算符sizeof操作数的评估

时间:2010-08-24 06:29:32

标签: 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); 
}  

我认为我不会增加,因为sz不是VLA但j会增加,因为arr是VLA 但是在输出中,i和j都没有增加。

4 个答案:

答案 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是否已在编译时替换为常量。