簡體   English   中英

在遺留編譯器中,邏輯否定是否已被實現為按位否定?

[英]could logical negation have been implemented as bitwise negation in legacy compilers?

我剛剛發現遺留代碼測試這樣的標志:

if( some_state & SOME_FLAG )

到現在為止還挺好!
但是在代碼中,我看到了一個不正當的否定

if( ! some_state & SOME_FLAG )

我的理解是它被解釋為(! some_state) & SOME_FLAG這可能是一個bug,而gcc在邏輯上咆哮着-Wlogical-not-parentheses ...

雖然它最終可能在過去有效!some_state被一些遺留編譯器實現為~some_state 有誰知道是否可能如此?

編輯

sme_state聲明為int(可能是32位,目標sme_state上的2個補碼)。
SOME_FLAG是一個常量設置為單個位0x00040000,因此SOME_FLAG & 1 == 0

邏輯否定和按位否定從來都不相同。 沒有符合標准的編譯器可以實現另一個。 例如,1的按位取反不是0,所以~1 != !1

表達確實如此! some_state & SOME_FLAG ! some_state & SOME_FLAG相當於(! some_state) & SOME_FLAG因為邏輯否定的優先級高於bitwise和。 這確實是可疑的 ,但原始代碼不一定是錯誤的。 在任何情況下,在這方面,程序更有可能是錯誤的,因為任何C實現都會以不同於當前標准的要求評估原始表達式,甚至在標准化之前。

由於表達式(! some_state) & SOME_FLAG!(some_state & SOME_FLAG)有時會評估為相同的值 - 特別是如果SOME_FLAG恰好擴展為1 - 也有可能即使它們不相等,它們的差異也不會在實際執行程序期間顯示。

雖然1989年之前沒有標准,因此編譯器可以按照自己的意願做事,但據我所知,沒有任何編譯器可以做到這一點; 如果您希望人們使用您的編譯器,更改運算符的含義將不是一個聰明的調用。

寫一個像(!foo & FLAG_BAR)這樣的表達式的理由很少; 結果只是!foo如果FLAG_BAR是奇數,或者如果是偶數則總是為零。 你發現的幾乎肯定只是一個bug。

遺留編譯器無法實現! 作為按位否定,因為當被否定的值超出{0,0xFF ... FF}集時,這種方法會產生不正確的結果。

標准要求的結果!x產生零對任何非零值x 因此,申請! 比方說,1會產生0xFF..FFFE,這是非零的。

遺留代碼按預期工作的唯一情況是SOME_FLAG設置為1

讓我們從最有趣(也是最不明顯)的部分開始:gcc邏輯上用-Wlogical-not-parentheses咆哮。 這是什么意思?

C有兩個不同的運算符,它們具有相似的外觀字符(但行為不同,用於非常不同的目的) - &是一個按位AND,而&&是一個布爾AND。 不幸的是,這導致了拼寫錯誤,就像打字=當你的意思==會導致問題時,所以一些編制者(GCC)決定警告人們“ &沒有括號作為條件”(即使它是完全合法的)減少錯別字的風險。

現在...

您正在顯示使用&代碼(並且不顯示使用&&代碼)。 這意味着some_state不是布爾值而且是數字。 更具體地說,它意味着some_state中的每個位可以完全獨立some_state相關。

舉個例子,讓我們假裝我們正在實施一個Pacman游戲,需要一個很好的緊湊方式來存儲每個級別的地圖。 我們認為地圖中的每個瓷磚可能都是牆,可能是一個收集的點,也可能不是,但可能是一個或不是櫻桃。 有人建議這可以是一個字節數組,就像這樣(假設地圖是30個瓷磚寬,20個瓷磚高):

#define IS_WALL         0x01
#define HAS_DOT         0x02
#define HAS_POWER_PILL  0x04
#define HAS_CHERRY      0x08

uint8_t level1_map[20][30] = { ..... };

如果我們想知道瓷磚是否安全進入(無牆)我們可以這樣做:

    if( level1_map[y][x] & IS_WALL == 0) {

相反,如果我們想知道瓷磚是否是牆,我們可以做以下任何一種:

    if( level1_map[y][x] & IS_WALL != 0) {

    if( !level1_map[y][x] & IS_WALL == 0) {

    if( level1_map[y][x] & IS_WALL == IS_WALL) {

因為它與哪一個沒什么區別。

當然(為了避免拼寫錯誤的風險)GCC可能(或可能不會)警告其中一些。

暫無
暫無

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

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