国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

坑人的運(yùn)算符

2019-11-14 16:28:14
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

 

一、運(yùn)算符優(yōu)先級(jí)

前兩天我在園子的首頁(yè)看到一篇隨筆,隨筆地址已經(jīng)找不到了(著實(shí)有點(diǎn)抱歉),不過(guò)其中的一個(gè)代碼片段還是記得一二,大概如下:

            Thread t = null;            string message = "I'm ..." + t == null ? "And ..." : "";            Console.WriteLine(message);

代碼很少,但我想有不少人會(huì)中招,最關(guān)鍵的問(wèn)題就是運(yùn)算符的優(yōu)先級(jí)了。這里是 C#參考 運(yùn)算符,根據(jù)這份優(yōu)先級(jí)順序,我總結(jié)出以下規(guī)律: 

最高:.(點(diǎn)) ()  []  i++  i-- 

其次:?jiǎn)文窟\(yùn)算符(i++ 高于 ++i)

然后:先算乘除余、后算加減、最后位移、比大小(大于小于 高于 相等和不等)

接下來(lái):Not And Or ( 即 ! , && , || )

最后:三目 、賦值 和 Lambda

這份優(yōu)先級(jí)順序已經(jīng)包含了大部分運(yùn)算符,只要不是遇到很變態(tài)的問(wèn)題,我想應(yīng)該可以搞定。

 

二、編譯器的貪心原則

該話題源于《java深入解析——透析Java本質(zhì)的36個(gè)話題》。(雖然源于Java話題,但同樣適用于C#、已驗(yàn)證)

三個(gè)加號(hào)該如何運(yùn)算呢? 代碼片段如下:

            int i = 10;            int j = 20;            int k = i +++ j; // 代碼未格式化,但可以正常編譯運(yùn)行            Console.WriteLine(k); // 輸出結(jié)果是多少呢? 是 30 還是 31?

我們先不看答案,先把代碼格式化一下、看看結(jié)果:  

int k = i++ + j; // 格式化后的結(jié)果,為何不格式化成 i + ++j; 呢? 答案是:編譯器的貪心原則

貪心原則:編譯器在分析符號(hào)的時(shí)候會(huì)盡可能多的結(jié)合有效的符號(hào)。  

因?yàn)?ldquo;+” 和 “++”都是有效的符號(hào),但是“+++”不是有效的符號(hào),因此,將表達(dá)式解析為了:i++ + j。

再舉個(gè)例子:a--b,本意為a - 負(fù)b。但是編譯器解析為了 a-- b,最終編譯不通過(guò)。所以代碼應(yīng)該這樣寫(xiě):a - -b; 

 

三、 i++你真的理解了嗎?

這個(gè)例子我第一次看到、是在一份筆試試卷上,如果你能說(shuō)出下面這個(gè)代碼片段的正確答案,那這部分就沒(méi)有必要看了,如果不能也許你走入了一個(gè)“誤區(qū)”。

            int i = 0;            i = i++;            Console.WriteLine(i); // 1 or 0?

我在記憶 i++和++i 的時(shí)候,不是記憶“先加”還是“后加”的,而是直接記住“運(yùn)算結(jié)果”。

i++的運(yùn)算結(jié)果:表達(dá)式的值等于 i    ,i的值自加1.

++i的運(yùn)算結(jié)果:表達(dá)式的值等于 i+1,i的值自加1.

也就是說(shuō):

i = i++; // 右側(cè)表達(dá)式的結(jié)果等于i本身,然后執(zhí)行賦值運(yùn)算符賦值,最后得到的i的結(jié)果還是 i本身.

 

補(bǔ)充:

一樓評(píng)論里給出了疑問(wèn),對(duì)于該疑問(wèn)我最簡(jiǎn)單的答案是:誤區(qū)——i++的運(yùn)算結(jié)果:表達(dá)式的值等于 i    ,i的值自加1。注意這里說(shuō)的是運(yùn)算結(jié)果,

表達(dá)式的值就等于i了,之后沒(méi)有再進(jìn)行自加1,而i的值進(jìn)行了自加1。

讓我們看一下IL代碼吧,看完之后也許一切疑問(wèn)都將煙消云散:

.method PRivate hidebysig static void  Main(string[] args) cil managed{  .entrypoint  // 代碼大小       17 (0x11)  .maxstack  3  .locals init ([0] int32 i)  IL_0000:  nop  IL_0001:  ldc.i4.0 // 將字面常量 0 入棧                                            棧結(jié)果:{0}  IL_0002:  stloc.0  // 將棧頂值賦值給第0個(gè)局部變量(即 i),棧頂值出棧                    棧結(jié)果: {}, i = 0  IL_0003:  ldloc.0  // 將第0個(gè)局部變量的值入棧 (即 0 入棧)                            棧結(jié)果:{0}  IL_0004:  dup      // 復(fù)制棧頂值                            棧結(jié)果:{0、0}  IL_0005:  ldc.i4.1 // 將字面常量 1 入棧                                            棧結(jié)果:{0、0、1}  IL_0006:  add      // 將棧頂?shù)膬蓚€(gè)值相加,棧頂?shù)膬蓚€(gè)值出棧,計(jì)算結(jié)果入棧              棧結(jié)果:{0、1}  IL_0007:  stloc.0  // 將棧頂值賦值給第0個(gè)局部變量(即 i),棧頂值出棧                   棧結(jié)果:{0}, i = 1 到此,完成 i++ 操作  IL_0008:  stloc.0  // 將棧頂值賦值給第0個(gè)局部變量(即 i),棧頂值出棧                   棧結(jié)果:{}, i = 0  到此,完成 = 賦值操作 由此可以看出最終執(zhí)行賦值操作的值其實(shí)就是最先入棧的 i 的值。  IL_0009:  ldloc.0    IL_000a:  call       void [mscorlib]System.Console::WriteLine(int32)  IL_000f:  nop  IL_0010:  ret} // end of method Program::Main

對(duì)于i++的問(wèn)題,我覺(jué)得還是記運(yùn)算結(jié)果為好,就像上面所總結(jié)的那樣。

 

四、零除以零等于什么?


有人也許會(huì)說(shuō):“小學(xué)生都知道啊,0不能做除數(shù)”,如果是這樣那恭喜你,答對(duì)了。但是只能得6分(滿分10分)。為啥呢?看代碼吧!

        static void Main(string[] args)        {            float x = 0;            float result = x / x;            Console.WriteLine(result); // 輸出結(jié)果:非數(shù)字            Console.Read();        }

此話題只是個(gè)引子,更多信息請(qǐng)參見(jiàn):Single.NaN。

 

坑人的運(yùn)算符,確實(shí)很坑人啊。

 


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 息烽县| 玉树县| 江川县| 伊吾县| 磐安县| 无为县| 沈丘县| 甘孜县| 丰县| 佛坪县| 濉溪县| 汉沽区| 玉林市| 瑞安市| 永德县| 会宁县| 康乐县| 亳州市| 彭泽县| 资阳市| 突泉县| 湖口县| 涪陵区| 墨脱县| 眉山市| 天柱县| 常德市| 保山市| 上犹县| 微山县| 星座| 武功县| 星子县| 云和县| 烟台市| 怀仁县| 钟祥市| 镇原县| 马边| 肃北| 黑山县|