繁体   English   中英

sizeof运算符中操作数的评估

[英]evaluation of operand in sizeof operator

由于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都不增加。

引用我对另一个问题的回答

“转换”归因于减法运算符。 使用逗号运算符可以看到类似的结果,也许更令人惊讶:

 printf("%zu\\n", sizeof(1, a)); 

也将打印sizeof(int *) ,因为逗号运算符导致在值上下文中使用它。

基本上,由于逗号运算符的缘故 arr 的类型是指针,并且VLA的大小不会出现在图片中。 有关详细信息,请参见我的链接答案。

没有太多的解释,但我怀疑它是针对逗号运算符的一些编译器优化。 逗号运算的值是最后一个表达式的值。 使编译器知道sizeof是一元运算符,并带有逗号运算符,因此除了最后一个表达式(不管最后一个是否引用VLA)之外,它都不会去求值。

我编写了一些测试程序(在Ubuntu 9.04上为gcc 4.3.3):

$ cat test.c#与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#不带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

它可能记录在某处,但我不知道在哪里看。

sizeof在编译时求值。 在C99中,对于可变长度数组,它将一直等到运行时。 选中此答案以解决类似问题。

编译器知道数组大小:显然是20。我不认为sz是VLA。 尝试使用数组大小​​作为函数参数,例如:

void Function(int size)
{
    int arr[size];
    ...
}

顺便说一句,要了解会发生什么,建议阅读编译器生成的汇编代码。 检查在编译时sizeof是否已被常量替换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM