簡體   English   中英

C / C ++`!a` vs`a == 0`

[英]C/C++ `!a` vs `a==0`

當我有一個整數或指針a ,事實證明兩者都是

!a

a==0

有相同的行為。 在非常低的水平上,計算速度方面是否存在一些差異?

性能不太可能存在差異,因為編譯器知道邏輯等價,因此沒有理由不能為兩者發出相同的代碼。

等價是小學,而不是一些聰明的定理:的意義 !a在標准定義的整數類型是“價值a等於0”(或嚴格地說詹姆斯指出,“不是(價值a不為0)” ),和意義!a為指針類型是“ a是空指針”(或嚴格來說“不是(價值a是一個非空指針)”。

但是,並不要求編譯器必須為兩者發出相同的代碼,因此C或C ++標准無法保證性能相同。

根據定義, ! 需要bool類型的操作數; 如果其操作數的類型為int ,則存在隱式轉換(這對於混淆是很好的,但通常應該避免)。 根據定義,int abool的隱式轉換是a != 0 所以!a!(a != 0) 在實踐中,很難想象任何編譯器都沒有生成完全相同的代碼!(a != 0)a == 0 ,所以性能當然不應該是一個考慮因素。 說出你的意思並且意味着你所說的:因為你要比較0 ,那就是應該寫的方式。

編輯:

正如史蒂夫傑索普指出的,如果該類型進行比較不int ,的正式定義!a!(a != static_cast<T>( 0 )其中T是類型a 。雖然隱式轉換通常傷害可讀性,我認為沒有人會堅持將0顯式轉換為另一種整數類型。另一方面,我系統地為浮點類型寫a == 0.0 ,而在C ++中,為指針類型寫a == nullptr - 其中涉及另一個隱式轉換,從std::nullptr_t到指針類型。並非所有隱式轉換都是相同的:-)。 (FWIW:我接受整數類型之間的隱式轉換,以及浮點類型之間的隱式轉換,只要它們沒有縮小,如C ++11§8.5.4/ 7中所定義,除了應該使用'\\0'之外,而不是0 ,用於字符數據;以及指針之間的隱式轉換,以及指針和std::nullptr_t之間的隱式轉換。整數類型到浮點類型的隱式轉換也不會打擾我,盡管我從不寫它們。但是就是這個。)

在C中沒有區別,兩個版本很可能生成相同的機器代碼。 不同的是風格。

它甚至可以在C標准中明確寫出(C11 6.5.3.3):

表達式!E等價於(0 == E)。

! 應該只用於有效布爾值的操作數。 不幸的是,C中沒有真正的bool類型,所有內容都被評估為int。 (盡管C99引入了一個_Bool類型和一個bool宏,但只要在表達式中使用它們,它們仍會被提升為整數。)仍然應該將表達式視為存在bool類型。 優秀的C程序員編寫的代碼假裝存在真正的bool類型。 (有關“有效布爾”的更多信息,請參閱MISRA-C:2012附錄D“基本類型”。)

對於所有其他操作數,應使用== 0 這包括普通整數和指針。 例如,寫if(!ptr)被認為是壞樣式,檢查指針的正確方法是if(ptr == NULL) (MISRA-C:2004 12.6)

出於類似的原因, if(ptr)被視為草率編碼。 因為if期望一個有效布爾的表達式。 正確的代碼使用if(ptr != NULL) ,這也更具可讀性和自我記錄性。 即使生成的機器代碼是相同的。 (MISRA-C:2004 13.2)

C ++是不同的,因為它有一個真正的bool類型。 操作數來! 預計將是bool,如果它不是bool,它將被轉換為一個。 C將執行相反的操作,如果操作數是bool,它將轉換為int。 盡管如此,這最終不會影響性能,因為允許編譯器將所有隱式轉換優化為最合適的類型,因為它不會改變代碼的結果。

同樣在C ++中,結果類型為! ==總是一個bool,而C中的結果總是一個int(你應該把它當作一個bool ......但它仍然是一個int)。

我期望在計算速度沒有區別!aa==0的整數和指針。

使用最能明確表達您意圖的變體。 對於整數,我總是使用`a == 0'。 有了指針這兩個版本對我來說都很好。

PS:性能差異並非不可能,但它應該非常小。 對於良好的優化編譯器,差異實際上是不可能的。 它將被視為一個錯誤並很快修復。

在許多情況下它們是相同的。 任何現代編譯器都會根據目標機器選擇最佳指令。 第一個在開發人員之間很受歡迎。

您應該考慮到它可以依靠的類型, a在超載的情況下運營商的==! (例如自定義對象)

考慮到這兩個語句,你可以執行的最佳優化是寫0 == a而不是a == 0

C存在一個小的差異, C版本不提供bool類型,在這個舊版本的C bool中作為一個int被處理,所以隱式轉換只是一個integer而不是一個bool ,這就是訣竅!!a帶有雙重否定的地方,這就是為什么這個技巧在語言的現代版本中沒用,但很大程度上采用舊的代碼庫。

除此之外,我不記得實質性的差異。

我總是我們!a在我自己的代碼,而只是因為它的短/簡單(在工作中,編碼標准說0 == a )。

正如其他人所說,編譯器將解決任何差異,並且無論是哪種情況,它都將執行某種檢查“值是否為零”並形成一個布爾值的結果。 無論哪種方式,最終結果應該非常相同。

上述是假設的類型a是簡單類型(整數/焦炭/布爾或浮點型)。 如果碰巧是classstruct ,那么!a版本將調用operator bool操作數,其中a == 0可能會使用不同的方法,例如operator== - 請注意這里的規則很復雜,並且一個人對另一個人的影響可能很大。

總之,對於簡單類型,它只是一種風格問題(在大多數編譯器中!)。 對於復雜類型,它取決於所涉及的類/結構的設計。

如果性能真的很重要,那么衡量不同解決方案之間的差異,看看在這種情況下哪種解決方案表現最佳

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM