簡體   English   中英

C:具有無符號操作數的一元減運算符行為

[英]C: unary minus operator behavior with unsigned operands

我似乎無法在 C 標准中找到完全定義具有無符號操作數的一元減運算符的行為的相關部分。

2003 C++ 標准(是的,C++,請多多指教)在 5.3.1c7 中說: The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand.

然而,1999 年的 C 標准沒有包含這樣一個明確的聲明,也沒有在 6.5.3.3c1,3 和 6.5c4 中明確定義一元行為。 在后者中,它說Some operators (the unary operator ~, and the binary operators <<, >>, &, ^, and |, ...) ... return values that depend on the internal representations of integers, and have implementation-defined and undefined aspects for signed types.) ,它排除了一元減號,事情似乎仍然模糊。

這個較早的問題指的是 K&R ANSI C 書的 A.7.4.5 節,其中說The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one

1999 年的 C 標准與本書中的上述引文等效的是什么?

6.2.5c9 說: A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

是這樣嗎? 或者還有什么我想念的嗎?

是的,6.2.5c9 正是您要查找的段落。

一元減號運算符對無符號操作數的行為與機器是否對有符號數使用二進制補碼算術無關。 相反,給定unsigned int x,y; 語句y=-x; 將導致y接收它必須保持的任何值以使x+y等於零。 如果x為零,則y也將為零。 對於x任何其他值,它將是UINT_MAX-x+1 ,在這種情況下, x+y的算術值將是UINT_MAX+1+(yy) ,當分配給unsigned integer ,將減去UINT_MAX+1從它,產生零。

在我所知道的每個實現中,負數被計算為二進制補碼......

int a = 12;
int b = -a;
int c = ~a + 1;
assert(b == c);

...所以負有符號整數和“負”無符號整數之間實際上沒有物理區別 - 唯一的區別在於它們的解釋方式

所以在這個例子中...

unsigned a = 12;
unsigned b = -a;
int c = -a;

... bc將包含完全相同的位。 唯一的區別是b被解釋為 2^32-12(或 2^64-12),而c被解釋為“正常”-12。

因此,無論“符號性”如何,都以完全相同的方式計算負數,並且無符號和有符號之間的轉換實際上是無操作(並且永遠不會導致溢出,因為某些位需要“剪切” -離開”)。

這已經晚了,但無論如何......

C 聲明(以一種相當困難的方式,正如其他答案中已經提到的那樣)

  • 任何無符號類型都是具有特定於類型的位數的二進制表示

  • 無符號類型的所有算術運算都已完成(mod 2^N),“mod”是模數的數學定義,“N”是用於表示類型的位數。

應用於無符號類型的一元減號運算符的行為就像該值將被提升為下一個更大的有符號類型,然后取反,然后再次轉換為無符號並截斷為源類型。 (這是一個輕微的簡化,因為整數提升發生在位數少於 'int' 的所有類型中,但我認為它已經足夠接近了。)

當將一元減號應用於無符號類型時,某些編譯器確實會發出警告,但這僅僅是為了程序員的利益。 恕我直言,該構造定義明確且可移植。

但如果有疑問,請不要使用一元減號:寫 '0u - x' 而不是 '-x',一切都會好起來的。 除非完全禁用優化,否則任何體面的代碼生成器都只會從中創建一個否定指令。

暫無
暫無

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

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