[英]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.