2016-02-23 17 views
1

我想確定我明白如果兩個不同寬度的整數與彼此按位或運算會發生什麼情況。最明智的選擇是用零填充較小的一個。我寫了一個小程序來測試這個。在C中定義的不同int寬度上的按位運算符是否已定義好?

看看這個示例代碼:

#include <stdio.h> 
#include <stdint.h> 
#include <inttypes.h> 

int main(void) 
{ 
    uint32_t foo = 0x00000000; 
    uint8_t bar = 0xFF; 
    printf("%"PRIu32"\n", (foo | bar)); 
    printf("%"PRIu32"\n", (bar | foo)); 
} 

如果我的猜測是正確的,我應該會得到255的兩倍。當我運行這個,我得到

255 
255 

這是預期和明確的行爲,它是安全的依靠?是否有鏈接解釋了不同int寬度的位操作的所有行爲?

+2

您不使用'int',而是使用'uint32_t'。這是一個無符號整數類型,但不一定是'unsigned int',明確地不是'(signed)int'。您還通過將錯誤的變量參數類型傳遞給'printf'來調用未定義的行爲。爲'uint32_t'使用正確的格式說明符(請參閱'inttypes.h')! – Olaf

+1

關於bithop:這應該通過一個非常簡單的搜索或在每本C書中找到。 – Olaf

+0

@Olaf謝謝你指出。我用'printf'不太好。我在我的代碼中編輯了它,並得到了相同的結果,所以我將編輯我的文章,以便它不會分心我的真正問題。 – DJMcMayhem

回答

2

作爲每C11標準,章節§6.5.12,按位或運算符

每個操作數應具有整數類型。

通常的算術轉換都對操作數執行。

所以,按位操作應該沒問題。

但是,在printf()的情況下,%d預計值爲int,您提供的值爲unsigned int。那是undefined behavior

您可以使用PRIu32宏從inttypes.h打印uint32_t

+1

%如果值大於INT_MAX,則對於unsigned int,d是未定義的行爲。如果值爲負,則%ud對於int是未定義的行爲。對於常見範圍內的值,有符號或無符號值的有符號或無符號格式都可以。 – gnasher729

+0

@ gnasher729什麼是'%ud'? –

+0

@SouravGhosh一個'%u'指令,然後是一個字符'd'當然。 – fuz

0

您的代碼做一些事情可能比你預期的幕後不同:

uint32_t foo = 0x00000000; 
uint8_t bar = 0xFF; 
printf("%zu\n", (foo | bar)); 

讓我們假設類型uint32_t爲您的系統unsigned int上。在這種情況下,表達(foo | bar)是由編譯器以如下方式處理:

  • 第一,bar被改變(推動)鍵入int(已知爲整數推廣的過程) - 這不會改變其數學值255的。
  • 然後,由此產生的int轉換爲unsigned int,因爲|的另一個參數的類型爲unsigned int。再次,數學值沒有任何變化,它仍然是255.
  • 最後,結果如您所期望的那樣爲255,而且它的類型爲unsigned int

您需要查看的相關主題是C處理整數提升和隱式轉換規則。

+1

沒有「積分促銷」,但_integer promotions_。 「int」沒有強制(除非'int'有32位以上,但是第二位沒有轉換爲'unsigned int')。 – Olaf

+0

@奧拉夫:通常我錯了,但是在這裏你失去了我。 –