C 語言中,a+=1 和 a=a+1、a++ 有區別嗎?

如題...初學沒找到兩個的區別


首先確認下題主問的是C而不是C++。

是的話,答案取決於題主問的問題是在哪裡的代碼,其中的a是什麼。

如果這是在普通函數里的代碼,而a是個普通的局部變數或者全局變數的話,那兩種寫法意義和作用都一樣,沒有區別。同一問題之前有一個了,問前請先搜索:C語言中 i = i + 2 和 i += 2有什麼區別? - C(編程語言)

但如果這是在宏里的代碼,而a是個宏參數,那就好玩了——兩種寫法的副作用次數可能不一樣。這是因為複合賦值運算符(compound assignment operator)保證其左操作數只求值一次。

看例子:

#include &

#define foo(a) a += 1
#define bar(a) a = a + 1

int main() {
int a[10] = { 0 };
int b[10] = { 0 };
int i = 0, j = 0;
foo(a[i++]);
bar(b[j++]);

printf("i = %d, j = %d
", i, j);

return 0;
}

這裡bar版本的宏里a出現了兩次,而傳給a的是個有副作用的表達式(b[j++]),這裡了就變成在一個表達式里用了多次副作用而導致未定義行為了。用Clang編譯會報警告,執行的話會看到這個Clang編譯的版本會顯示i與j的值不一樣:

$ clang xx.c
xx.c:11:10: warning: multiple unsequenced modifications to "j" [-Wunsequenced]
bar(b[j++]);
^~
xx.c:4:16: note: expanded from macro "bar"
#define bar(a) a = a + 1
^
1 warning generated.
$ ./a.out
i = 1, j = 2

所以說在宏里的話要小心了喔。


都是表達式的話,沒區別

RX大神提到的實際上是宏和預處理器的語法問題,和+= = +本身沒有關係

那些說執行過程不一樣的,編譯器優化不是吃白飯的


不要糾結細枝末節了。隨你喜歡用哪個。

這是編譯器應該考慮的問題,而不是程序員需要考慮的問題。


放到if,for,while裡面有區別

if(a=a+1)

if(a+=1)

if(a++)

(a=a+1),(a+=1),跟(++a)一樣,跟a++還是有區別。


沒有區別,不要糾結了。


這段單獨的代碼沒有任何區別


其實我也不太清楚。

個人覺得假如a是數值型,那麼應該沒有什麼區別;假如是對象型,應該有區別。


學彙編時發現,只有a+=1沒有a=a+1,

學c++時發現,有的類的+是用+=實現的,

所以一度以為a+=1更快,

後來知道,編譯器並不死板,而且會優化的,


門外漢怒答一發!

趁早把譚浩強的破書給扔了!!


有著功夫研究破問題不如多看看書多自己親自實踐


左邊是C語言的代碼,右邊是編譯成彙編後的,(這個沒有關掉編譯器優化)

a+=1;

a++;

a=a+1;

很顯然,沒有差別,

addl $1, -4(%rbp)

addl $1, -4(%rbp)

addl $1, -4(%rbp)

下面關掉編譯器優化

不知道是不是我是不是關上了,

$ cat a.c

int main(){

int a;

a+=1;

a++;

a=a+1;

return 0;

}

$ gcc -O0 -S a.c -o a.s

$ cat a.s

.file "a.c"

.text

.globl main

.type main, @function

main:

.LFB0:

.cfi_startproc

pushq %rbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movq %rsp, %rbp

.cfi_def_cfa_register 6

addl $1, -4(%rbp)

addl $1, -4(%rbp)

addl $1, -4(%rbp)

movl $0, %eax

popq %rbp

.cfi_def_cfa 7, 8

ret

.cfi_endproc

.LFE0:

.size main, .-main

.ident "GCC: (Debian 4.9.2-10) 4.9.2"

.section .note.GNU-stack,"",@progbits還是這個樣子,其實我感覺也應該有區別,可是。。。。。。還是一樣


這個,要是較真的話,還是有區別的

首先,兩者在語法是有一定區別的,當然,我想這裡討論的是語法正確情況下兩者的區別,所以我們可以不用去關心語法上的差異了。

然後,我們繼續看C99標準

6.5.16.2:3

A compound assignment of the form E1 op= E2 differs from the simple assignment expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once.

簡單說,區別就在於a += 1中a嚴格的僅求值一次。

但是需要提醒的是,由於assignment operators的operand的求值順序是unspecified (注意,是unspecified不是undefined喲),所以任何想要利用這條來寫的代碼都是不明智的。雖然,如果你的環境有明確的定義,利用這條所寫出的代碼並不能算錯誤…………


如果用彙編的思想去想的話,這三個代碼是有區別的(假設 a 為無符號 8 位):

a = a + 1 的執行過程:

MOV AL, a

ADD AL, 1

MOV a, AL

三條三位元組機器指令。

a += 1 的執行過程:

ADD a, 1

一條三位元組機器指令。

a++ 的執行過程:

INC a

一條雙位元組機器指令。

在對單片機時鐘晶振等對機器指令執行時間要求較高的場合,這三條指令是有區別的。純粹的編程解決問題,可以視為沒有區別。


這是一個大神判定題

說沒卵用的,都是沒有實際項目經歷的。

就這麼個問題,如果涉及到指針引用的時候,能讓人頭疼死


不同意樓上大部分人的答案。

a+=1、a=a+1、a++在不同的場合具有不同的意義,除了對a表達的意義(宏或者變數或者指針變數或者表達式甚至函數)做出限定外,還應對其出現的場合做出限定,假定a是變數,則a+=1; a=a+1; a++;的運算結果一致。

想到後再繼續補充,眾位輕噴。


編譯到彙編級別是沒有區別的


a++有一個中間變數

類似於

int temp = a + 1;

// use a to do something

return temp;


前Java碼農試答,如有錯誤,請多關照。

以下僅討論a是整形(int)變數:

不考慮上下文的情況下,a+=1 和 a=a+1、a++作為單獨一條語句的執行結果是相同的,但是原始語義有區別。在編譯不加優化的情況下生成的彙編代碼應該是不同的:a+=1操作數和操作結果已經在語句中明確表示是同一個地址,可以提示編譯器對此特殊情況進行優化;a++這種自增操作實際上x86彙編中有專用指令,也可以提示編譯器對此特殊情況進行優化;而a=a+1就是最原始的寫法,不帶有任何優化的提示。

綜上所述,這三種寫法對用戶(對編譯器來說,用戶就是程序員)來說是等價的,基本是因為太古時代的編譯器不是太聰明,需要用戶提示才能完成一些優化。例如C語言中的register關鍵字,大意是建議編譯器把指定的變數放在寄存器中來獲取更快的讀寫速度,當然是否真的放在寄存器中就由編譯器自行決定了。

以上都是太古時代的編譯器,對於現代編譯器來說編譯器後端的局部優化目前已經相當聰明了,可以自動完成這類優化(比如特殊情況下的a*2與a&<&<1,a%4與a3),可以完全不必再對編譯器耍這種小聰明了。a=a+1和a++哪個執行更快的討論就像討論鑽木取火的時候應該用楊樹好還是用榆樹好……

發現似乎跑題了


題主應該和我一樣剛開始學C,目前我所知的狀態下,這三個是一樣的。

b=a++ b=++a 這種才不一樣,前者是先賦值再+,後者是先+後賦值


除了應付譚書的期末考試外,這個問題並無亂用


推薦閱讀:

郝斌的 C 語言教程怎麼樣?
為什麼學c語言我只會寫計算程序?
c語言中x*x和pow(x,2)哪個計算更快一點?
2==c會導致的這樣的異常嗎?
c語言可以釋放數組中的單個元素結構么?

TAG:C編程語言 | C語言入門 |