評價

2010-08-24 122 views
2

由於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但強會增加因爲arr是VLA。
但是在輸出中,i和j都沒有增加。

+0

這是關於C而不是C++的問題。在C++中不存在VLA。 – 2010-08-24 07:22:34

+0

哦,有人把它標記爲C++。壞人。 – 2010-08-24 07:46:29

回答

0

編譯器知道數組的大小:顯然是20.我不認爲sz是VLA。嘗試使用使用數組大小​​的功能參數,eaxmple:

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

BTW,瞭解發生了什麼,建議閱讀編譯器生成的彙編代碼。在編譯時檢查sizeof是否已被一個常量替代。

+0

在這種情況下,編譯器確實知道數組的大小,但它在技術上是VLA,因爲sz是一個變量,而不是常量。即使它是一個常量(const int sz = 20;),也不會使數組變成VLA(它總是具有相同的大小)。 – 2010-09-25 02:20:58

1

sizeof在編譯時評估。在C99中,對於可變長度的數組,它將一直等到運行時。檢查this answer到類似的問題。

4

引用my answer to another question

的 「轉化率」 是由於減法運算符。你可以看到類似的,也許更令人驚訝的,使用逗號運算符的結果是:

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

也將打印sizeof(int *),因爲導致一個值上下文中的習慣逗號操作符的。

基本上,由於逗號運算符,the type ofarr是一個指針,和VLA的大小不進入圖片。詳細信息請參閱我的鏈接答案。

+0

好的..我明白了。那麼有沒有一種方法可以利用這個事實「如果它是一個vLA,評估操作數的大小」來增加或修改某些其他操作數,正如我在此嘗試的那樣? – 2010-08-24 08:06:07

+0

@Happy:我不會稱之爲「利用」,它更像是「濫用'sizeof'運算符」。你究竟想要做什麼? – 2010-08-24 08:23:42

2

沒有太多的解釋,但我懷疑這是一些逗號運算符的編譯器優化。逗號操作的值是最後一個表達式的值。編譯器知道sizeof是一個一元運算符,並且帶有逗號操作,所以除了最後一個表達式(不管最後一個是否是對VLA的引用)之外,它都不用去評估它。

我寫了一些測試程序(在Ubuntu 9.04的gcc 4.3.3):

$貓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測試。 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測試alt.c

$貓測試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 

可能在某處證明,但我不知道在哪裏看。