簡體   English   中英

轉換具有不同容量的整數

[英]Converting integers with different capacity

我有以下代碼:

// ---- third party library code ----
struct Point { int16_t x, y; };
void third_party_library__getPoint(Point*);
void third_party_library__setPoint(const Point*);

// ---- my library code ----
void move_point(int dx, int dy)
{
    Point pt;
    third_party_library__getPoint(&pt);
    pt.x += dx;
    pt.y += dy;
    third_party_library__setPoint(&pt);
}

pt.x += dx; 產生警告
conversion from 'int' to 'int16_t', possible loss of data

我該怎么辦?

  1. 禁用這些行的警告
  2. 將警告源移動到接口:make dxdy int16_t,因此將使用move_point函數的人將處理此問題。
  3. 只需將dxdy為int16_t。
  4. 添加assert(dx <= 0x7FFF && dx >= -0x8000 && "too large 'dx' value")並希望它在我運行調試版本時會出現。

你應該制作dx和dy int16_t,如果你施放它們你只是隱藏它並且使用你的代碼的人將不會看到那些警告並且不知道問題。 因此,讓另一方的人處理警告,至少他們確定功能。

對我來說,這里有3個相關但不同的點:

A. 處理溢出

實際上,這里有兩個部分: 轉換溢出和加法溢出。 即使你把int16_t作為輸入,在+=階段仍然會有溢出,你必須決定如何處理它(當然你可以簡單地忽略它,但這也是一個選擇,好吧 -明確的后果)。

B. 告知用戶有關限制的信息

通過選擇(3)選項 - 移動到界面,您將通知用戶第一次溢出而不是第二次溢出。 此外,它不是通知用戶的唯一方式。 有時,更好的方法是在文檔中包含“限制”部分,以便立即明確。

C. 避免警告

一旦您決定使用(A),您可以根據您的決定進行轉換,從而使編譯器滿意。


您的(1)和(3)基本上是相同的,盡管人們不喜歡警告抑制。 這些選項僅回答避免 ,但不回答交易通知

(2)忽略第二次溢出,並將第一次溢出發送給用戶。 所以它確實避免和部分通知 ,忽略一半的交易 ,並將后半部分留給用戶。

(4)只是關於Inform ,但與DealAvoid無關。


我該怎么辦? 首先,我將決定如何處理溢出 - 取決於應用程序它可能是完全不同的,即它可能是標准溢出行為或截斷到最大可能值。 然后我會考慮如何正確地通知我的用戶 - 這取決於文檔的組織方式,如果斷言/異常是可接受的等等。最后,我會根據這一點避免警告,通過檢查溢出並根據交易策略。

假設你確定這里確實沒有錯誤(變量將永遠不會超過你關心的第15位),我會選擇“cast”的一些變體。

在這種情況下,我通常為兩個整數類型做的是一個構造函數:

pt.x += int16_t(dx);

對於閱讀此代碼的人來說,這應該是非常清楚的,事實上你確實想要丟棄16日以后的任何位。

如果你的實現無法應對over int16_t,那么你應該使用int16_t。

我更喜歡4 ,但最好的選擇取決於背景(例如性能考慮因素)。

  1. 禁用這些行的警告

    這很糟糕,因為禁用警告會增加代碼的污垢(例如,禁用警告的語法取決於編譯器)

  2. 將警告源移動到接口:make dx和dy int16_t,這樣一個將使用move_point函數的人將處理這個問題

    這很糟糕,因為您可能希望將來升級第三方庫而無需更改庫的界面

  3. 只需將dx和dy轉換為int16_t。

    這很糟糕,因為它可能會默默地導致溢出(顯然)。

    BTW只使用pt.x += int16_t(dx)不會“修復”警告; 如果要隱藏警告,請使用pt.x = int16_t(pt.x + dx) (或某些替代的轉換語法)

  4. 添加斷言(dx <= 0x7FFF && dx> = -0x8000 &&“太大'dx'值”)並希望它在我運行調試版本時會出現。

    這是一些毛茸茸的語法,但我想這是最不邪惡的(它的唯一缺點,除了語法,是性能,我們可以忽略它)。 您還可以使用以下語法(避免幻數):

     assert(int16_t(dx) == dx); 

添加斷言(dx <= 0x7FFF && dx> = -0x8000 &&“太大'dx'值”)並希望它在我運行調試版本時會出現。

好吧,顯然你必須處理“潛在的”錯誤(我稱之為一個完整的錯誤,順便說一句)。

為了接受警告(知道只有16位數字將被傳遞給你的函數),你可以添加一個強制轉換,它表示你在扔掉16個更高位時你正在做的事情。

所有這些都說假設您有32位或64位平台。

暫無
暫無

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

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