[英]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.