我對C 表示式的理解

2022-02-10 20:19:16 字數 1872 閱讀 5481

1inta =

2;

2intb =

9; 3a

^=(b

^=(a

^=b));

4console.writeline(",

", a.tostring(), b.tostring());

1inti=

0;

2intj=

(i++)+

(i++

); 3j

=?

j的值是多少?2麼?不是,正確的結果是1。

為啥會有這樣的結果,難道是編譯器的bug麼?其實不然,編寫編譯器的人可不是數學白痴,是我們對計算機的理解有誤。

c#中,表示式的計算遵循乙個規律:從左到右依次計算。

例如,z= x operation y,計算機依次計算x,y的值,然後operationx和y,最後賦值給z。

同理,z = x operation1 ( x operation2 y),計算機則把(x operation2 y)當做乙個變數temp。此時z = x operation1 temp。然後計算機再計算temp表示式,並壓棧,計算完temp表示式後,將結果出棧。這是個遞迴過程。注意:這個過程中,x與temp是兩個並列的表示式,如果temp中有對x進行再操作,並不會影響x的結果。因此表示式規律是從左到右依次計算,x在左,已經計算完畢。如果是z = temp operation1 x,那麼temp中對x的操作將會影響到x本身。

ok,理論分析完畢,讓我們來實踐一下為什麼上面2個表示式的結果令人詫異。

對於第乙個表示式:a ^= (b ^= (a ^= b))。先將運算子分解:a = a ^ (b = b ^ (a = a ^ b)); 這樣看起來更清晰。

1. 計算機分解表示式為 a = a ^ temp1。計算左邊的a,a本身是乙個變數,因此a用2來代替。接下來計算右邊的temp1表示式,發現其中比較複雜,無法直接用值來代替,因此開始對temp1堆疊計算。

2. temp1 是 b = b ^ (a = a ^ b)。計算左邊,b是變數,可以直接賦值為9。右邊是表示式,用temp2代替。

3. temp2 是 a = a ^ b。計算左邊,a是變數,替換為2; 右邊,b也是變數,替換為9。並計算出temp2=2 ^ 9 = 11。

4. 回歸計算temp 1 = 9 ^ temp2 = 9 ^ 11 = 2,也就是b = 2。

5. 回歸計算a = 2 ^ temp1 = 2 ^ 2 = 0。也就是a = 0。

ok,這樣0, 2結果就出現了。

對於第二個表示式: j = (i++) + (i++);。

1. 先計算左邊的表示式,i++,因為是字尾,所以(i++)表示式返回i,此時i = 0, 意味著返回0。

2. 執行++運算子,0++就是1,因此i = 1;

3. 計算右邊的表示式(i++),也是字尾,因此返回i ,此時 i = 1,意味著返回1;

4. 執行++運算子,1++就是2,因此i = 2;

5 賦值給j. j = 0 + 1 = 1。

綜上,其實不是什麼編譯器的bug,而是計算機的做法永遠是死腦筋的。

還有,實際專案中千萬不要出現這樣的表示式,寧可多寫幾行,也不要堆在一行,我們一定要遵循《**規範》。這也是為了提高**的可閱讀性和可維護性。

int i = 0; int j = (i--) + ((i++) + (++i)); 計算結果i 和 j 分別是多少?

自己對Lambda表示式的理解

lambda表示式其實是乙個簡寫的匿名內部類 而之所以能簡寫到僅僅一行 就能實現功能是由於一定的約束條件 總所周知,想要用匿名內部類,就要實現內部類的抽象方法。而如果乙個類有兩個以上的抽象方法時,由於無法定位方法,就無法進行進一步的縮寫 所以 lambda表示式的乙個要求就是 抽象方法只有乙個,那麼...

理解正值表示式

最近用到了python裡面的re這個library,每次用到的時候有點不明所以,所以還是搜搜資料然後寫一下筆記來方便理解和使用吧。正規表示式這個名詞的意思大概就是根據使用規則來提取表示式,也就是說,利用約定的語法規則去提取你想要的東西 以下是基本的一些規則,理解了規則,正規表示式就很清晰了 等價符 ...

查詢表示式理解

listp new list p.add new product p.add new product p.add new product p.add new product p.add new product p.add new product ienumerablelist2 from x in ...