2012-08-03 56 views
10

我正在從遺留代碼中刪除gcc警告。如何解決:「轉換爲C代碼中的不同大小的整數的指針」警告?

是否有可能通過抑制鑄字「轉換爲指針從大小不同的整數」警告:

example: 

some_struct *ptr = func() // func() returns an integer. 

是否有人可以指導我如何解決這樣的GCC警告?

+7

爲什麼你想要將一個整數放入一個結構指針? – Jay 2012-08-03 13:40:59

+0

這是可能的,但是這種情況是正確的解決方法。 – 2012-08-03 13:41:53

+0

是否存在「輸出」差異的重載?(不是輸入參數) – 2012-08-03 13:43:19

回答

19

首先,如果您可以修復func(允許修改其來源),然後修復它。如果它的計算可以用指針完成,那麼用指針和返回指針來完成它們。有時候有理由將地址作爲整數處理(例如,處理特殊代碼中的對齊問題)。在這種情況下,請將func更改爲使用uintptr_t類型(在stdint.h中定義)。它被設計用於在必要時將指針視爲整數。 (也有intptr_t如果由於某種原因有符號算術更好,但我通常會發現無符號的uintptr_t不那麼麻煩。)func最好在返回時將uintptr_t轉換爲指針,因此func的返回類型將是一個指針(可能是some_structvoid)。

如果您無法修復func,那麼您可以使用強制轉型告訴編譯器您打算執行正在執行的轉換。然而,這個特定的錯誤信息告訴你,你不僅僅是將一個整數轉換爲一個指針,而是將一個大小的整數(例如四個字節)轉換爲另一個大小的指針(例如八個字節)。很可能這個代碼最初是爲func返回的整數類型與指針類型具有相同大小的系統編寫的,但您現在正在指針類型大於或小於整數大小的系統上進行編譯。

在這種情況下,您必須確保func執行的計算適用於新體系結構。如果它只返回一個32位的數值,它是否總是保持正確的值?也就是說,丟失的高32位不會丟失什麼? func應該計算的地址不會超過它使用的整數類型的最大值嗎?如果func正在使用帶符號的整數類型,請考慮符號位。

如果您確定func返回的值是正確的,那麼您可以使用明確的轉換,例如:some_struct *ptr = (some_struct *) (intptr_t) func();

6

我的gcc沒有給出你引用的警告。這也會很奇怪,因爲代碼中沒有強制轉換。

我得到警告

assignment makes pointer from integer without a cast 

注意 「不進行強制轉換」 部分。因此,你可以讓GCC無聲鑄造(不改變行爲):

some_struct *ptr = (void*)func(); 

然後,你會得到你的警告(「劇組到指針由大小不同的整數」)當且僅當func返回類型不適合爲地址。這可以通過將func()額外地鑄造成合適的整數類型來消除,例如, intptr_t

some_struct *ptr = (void*)(intptr_t)func(); 

這一切你真的想錯了大小的整數轉換爲指針的假設下。重新編寫代碼可能是一個更好的主意。

3

這裏有兩種可能性:

  1. func是鑄造實際指向的整數;它稍後用作指針。
  2. func返回存儲在指針中的整數; ptr稍後將轉換爲整數並用作整數。

在第一種情況,從func返回值將丟失信息,並且潛在地導致崩潰或更糟,如果int比數據指針的大小,這將是在大多數64-bit memory models(包括Windows較小和Linux)。在這種情況下,您應該將退貨類型func更改爲intptr_t;見Using intptr_t instead of void*?Why/when to use `intptr_t` for type-casting in C?

在第二種情況下,它不是一個問題,而是處理通過intptr_tsome_struct *ptr = (some_struct *)(intptr_t)func();和更高版本int value = (int)(intptr_t)ptr;投遞的字節順序問題。有關此問題的討論,請參閱GLib Type Conversion Macros

相關問題