簡體   English   中英

整數文字的類型和〜在C中

[英]Type of integer literals and ~ in C

我是C初學者,我對C答案書中的以下示例感到困惑。

在系統中查找unsigned long long大小的一種方法是鍵入:

printf("%llu", (unsigned long long) ~0);

我不知道為什么這個語法有效?

在我的系統上, int是32位, long long是64位。
我所期望的是,因為0是整數類型的常量,所以~0計算32位整數的否定,然后由unsigned long long轉換運算符將其轉換為unsigned long long整數。 結果應該給出2 32 - 1。

不知何故,看起來~運算符已經知道它應該作用於64位?
編譯器是否將此指令解釋為printf("%llu", ~(unsigned long long)0); 這聽起來不對,因為演員和~具有相同的優先權。

不知何故,看起來〜運算符已經知道它應該作用於64位?

它不是~運算符,它是演員。 以下是根據標准完成整數轉換的方法:

6.3.1.3有符號和無符號整數

  • 當具有整數類型的值轉換為除_Bool之外的另一個整數類型時,如果該值可以由新類型表示,則它將保持不變。
  • 否則,如果新類型是無符號的,則通過重復地添加或減去一個可以在新類型中表示的最大值來轉換該值,直到該值在新類型的范圍內。
  • 否則,新類型將被簽名,並且值無法在其中表示; 結果是實現定義的,或者引發實現定義的信號。

signed int ~0的值對應於具有負值的二進制補碼表示的系統上的-1 它不能用unsigned long long ,因此第一個要點不適用。

第二個要點確實適用:新類型是無符號的,因此unsigned long long MAX被加到-1一次,以使結果進入unsigned long long的范圍。 這與符號擴展-1到64位具有相同的效果。

0的類型為int ,而不是unsigned int 因此, ~0 (在使用二進制補碼整數表示的機器上,這是今天使用的所有機器)將為-1,而不是2 32 - 1。

假設一個64位unsigned long long(unsigned long long) -1-1模2 64 ,即2 64 - 1。

0是一個int

~0仍然是一個int ,即值-1

intunsigned long long只是為了匹配printf期望的類型與轉換llu

但是,-1的值擴展為無符號長long,對於4字節int應為0xffffffff,對於8字節int應為0xffffffffffffffff。

根據N1570委員會草案:

6.5.3.3一元算術運算符

  1. 〜運算符的結果是其(提升的)操作數的按位補碼 (即,當且僅當未設置轉換后的操作數中的相應位時,才會設置結果中的每個位)。 整數提升在操作數上執行,結果具有提升類型。 如果提升類型是“ 無符號類型 ,則表達式~E等於該類型中可表示的最大值減去E”。

§6.2.6.2語言45

(補充)。 其中的哪一個適用於實現定義 ,符號位為1且所有值位為零的值(對於前兩個),或者符號位和所有值位1(對於補碼)是否為陷阱表示或正常值。 在符號和幅度以及1'補碼的情況下,如果該表示是正常值,則稱為負零。

因此,代碼的行為:

printf("%llu", (unsigned long long) ~0);

在某些機器上實現定義和未定義 - 不是按預期 - 依賴於機器中整數的內部表示。

根據6.5.3.3節,批准的編寫代碼的方式是:

printf("%llu", (unsigned long long) ~0u);

此外, ~0u類型是unsigned int,當你將它轉換為unsigned long long int時,格式字符串是llu 使用格式字符串%u打印~0u

要學習類型轉換的基本概念,您可能希望閱讀: C / C ++中的類型轉換究竟是什么?

暫無
暫無

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

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