簡體   English   中英

c ++在有符號和無符號之間進行隱式轉換的代碼的安全性

[英]c++ safeness of code with implicit conversion between signed and unsigned

根據有符號和無符號整數類型之間的隱式轉換規則, 這里這里討論,當將unsigned intint相加時,signed int首先轉換為unsigned int

例如,考慮以下最小程序

#include <iostream>

int main()
{
   unsigned int n = 2;
   int x = -1;

   std::cout << n + x << std::endl;

   return 0;
}

然而,程序的輸出是預期的1: x首先被轉換為unsigned int ,而n的和導致整數溢出,給出“正確”的答案。

在前一個代碼中,如果我確定n + x是正數,我可以假設unsigned int nint x和給出了期望值嗎?

在前一個代碼中,如果我確定n + x是正數,我可以假設unsigned int n和int x之和給出了期望值嗎?

是。

首先,使用模運算將有符號值轉換為無符號:

如果目標類型是無符號的,則結果值是與源整數一致的最小無符號整數(模2 n ,其中n是用於表示無符號類型的位數)。

然后使用模運算添加兩個無符號值:

無符號整數應遵守算術模2 n的定律,其中n是該特定整數大小的值表示中的位數。

這意味着您將獲得預期的答案。

即使,如果結果在數學意義上是負的,那么C ++中的結果將是模數等於負數的數字。

請注意,我在這里假設您添加兩個相同大小的整數。

我認為你可以肯定並且它不是實現定義的,盡管當涉及到不使用二進制補碼表示負值的系統時,該語句需要對標准進行一些解釋。

首先,讓我們陳述清楚的事情:無符號積分不會溢出,而是采用模2 ^ nrOfBits值(參見此在線C ++標准草案 ):

6.7.1基本類型

(7)無符號整數應遵守算術模2n的定律,其中n是該特定整數大小的值表示中的位數。

因此,只需將負值nv正確轉換為無符號整數位模式nv(conv) ,使x + nv(conv)始終與x - nv相同。 對於使用二進制補碼的系統的情況,事情是清楚的,因為實際上設計了兩個補碼使得該算法立即起作用。

對於使用其他負值表示的系統,我們必須仔細閱讀標准:

7.8完整轉換

(2)如果目標類型是無符號的,則結果值是與源整數一致的最小無符號整數(模2n,其中n是用於表示無符號類型的位數)。 [注意:在二進制補碼表示中,此轉換是概念性的,並且位模式沒有變化(如果沒有結束)。 -endnote]

正如腳注明確指出的那樣,在二進制補碼表示中,位模式沒有變化,我們可以假設在2s以外的系統補碼中,將發生實際轉換,使得x + nv(conv) == x - nv

因此,由於7.8(2),我會說你的假​​設是有效的。

暫無
暫無

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

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