c語言中 if(A&&B)判斷條件,如果A已經為假了,編譯器還會繼續計算B的真假值嗎,該如何判斷?
RT,看到書上有個判斷語句是if(pre->next != NULL pre->next->data != 0) 就比較好奇若是此時pre->next已經是空指針了,對後面pre->next的data域的訪問不就是非法的了么。恰好身邊沒電腦可以驗證我的想法,不知有無大神能解我的疑惑,不勝感激
不會:如果第一個操作數與 0 相等,不會對第二個操作數進行求值。
The operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
If the first operand compares equal to 0, the second operand is not evaluated.
C89 §3.3.13 · C99 §6.5.13/4 · C11 §6.5.13/4 · Logical operators
p.s. 因為 C 語言有未定義行為的概念,所以通過實驗驗證想法有可能得出片面甚至錯誤的結論,正確的做法是查文檔。
p.p.s. C++ 同理,除了定義里用的不是 0 和 1 而是 false 和 true 之外基本是一樣的。
不會。這是短路計算。
類似的,if (A || B) 如果A表達式的結果是真,那麼就不會計算B表達式了。
嚴格講,C語言沒有真值和假值,邏輯判斷把非0看成真,0看成假。
額~這應該是一道C語言的必考題,我參加過的所有編碼考試中都有這道題。
就是不用。一個條件滿足的就不會去執行後面的判斷了
你的 C 語言教材難道不講這個知識點?
B不管真假,結果已經註定是假,繼續求值沒什麼意義
不用多想,看看下面這個c函數編譯出來的彙編文件是怎麼樣就可以了:
int f(int a, int b)
{
if (a b) {
return 1;
} else {
return 0;
}
}
編譯:
unix&> gcc -S test.c -o test.s
生成的彙編文件如下:
.file "test.c"
.option nopic
.text
.align 2
.globl f
.type f, @function
f:
addi sp,sp,-32
sw s0,28(sp)
addi s0,sp,32
sw a0,-20(s0)
sw a1,-24(s0)
lw a5,-20(s0)
beqz a5,.L2
lw a5,-24(s0)
beqz a5,.L2
li a5,1
j .L3
.L2:
li a5,0
.L3:
mv a0,a5
lw s0,28(sp)
addi sp,sp,32
jr ra
.size f, .-f
.ident "GCC: (GNU) 8.2.0"
riscv32體系結構調用協定中,用寄存器a0至a7傳遞參數,用寄存器a0或{a1, a0}傳遞返回值。
f中的兩條sw指令將a0和a1存入堆棧,也就是局部變數a和b;
然後先取局部變數a的值存入寄存器a5,並判斷a5是否為假,如果為假就跳轉到.L2(不再判斷局部變數b)。否則,繼續取局部變數b的值存入寄存器a5,再判斷是否為假,如果為假仍然跳轉到.L2。否則,利用a5暫存返回值1,並跳轉到.L3;
.L2利用a5暫存返回值0,並執行.L3;
.L3將暫存返回值寄存器a5的值存入返回值寄存器a0,釋放當前棧幀並返回。
c語言的種種規則只是一份標準文件,背誦標準文件不如看看被固化為程序的標準文件(編譯器)對輸入的行為。
通常編譯器是不知道運行時變數的值的,所以兩邊的表達式都會被編譯成二進位。但是如果編譯時可以肯定左邊是偽,那麼大多數編譯器會直接報警,或者直接把右邊和整個語句塊優化沒了。
另外我覺得萬一你想說的應該不是編譯器而是運行時,那隻能對你說:Read the Fucking Book不會,且的意思前邊已經為假了後邊就不會再執行了!
計算與否是C語言標準規定的么?假如後面的算式改變某個變數的值,不同的實現會導致程序結果不一致的吧。
不會,這是短路問題。外:可以考慮更換你的C教材,如c primer plus
百度
| 和||
8和88(手機沒找到它)
區別
這種事是編譯器乾的,所謂優化就是類似的東西,只是你說的這種,是連初學者都會考慮的優化,那寫編譯器的大神,怎麼會考慮不到?
推薦閱讀: