2010-03-06 112 views
3

我嘗試移植到64位的C源代碼在32位環境中沒有任何警告地運行。當我在64位Linux環境中編譯GCC(Ubuntu的4.4.1-4ubuntu9)4.4.1編譯,它顯示下面的警告主要是:移植C編寫的32位源代碼到64位

warning: cast to pointer from integer of different size 

的上述警告是最。我用uintptr_t類型和大多數這些警告被刪除。我可以使用uintptr_t將類型int/unsigned int更改爲64位有利。但我怎麼能更改以下類型進行兼容64位:

typedef void* POINTER; 

我已經改變了下面的代碼:

typedef unsigned int ABC; 

typedef uintptr_t ABC 

我有以下警告:

warning: passing argument 2 of ‘function’ from incompatible pointer type 
note: expected ‘ABC *’ but argument is of type ‘unsigned int *’ 

Mor eover,改變類型定義爲uintptr_t的較早前int或unsigned int類型後,我遇到大部分的警告如下:

warning: inlining failed in call to ‘abc_StringCopy’: call is unlikely and code size would grow 

功能tptp_StringCopy如下:

static __inline__ char* abc_StringCopy(void) 
{ 
    char *copy; 
    copy = (char*)Malloc(yyleng+1); 
    strcpy(copy, yytext); 
    return copy; 

哪有我擺脫了這些警告?

+0

gcc 4.3.3在64位Slackware說unsigned long int是8個字節,它等於指針的大小。 – 2010-03-06 21:48:34

+0

你似乎無法理解「int *」和「int」之間的區別。簡單地消除編譯器警告不會讓你通過移植應用程序,你需要更好地理解C,所以你可以理解你在做什麼。 – mctylr 2010-03-06 22:13:51

回答

0

我並不完全清楚這種情況,但似乎您已將unsigned int更改爲uintptr_t。前者是一個無符號整數,後者是一個無符號int 指針

一般來說,這不是一個有效的替代。

此外,你說的代碼「運行時沒有32位的警告」,但編譯爲64位給你的警告。但它是否在沒有警告的情況下運行並不重要。也許你的意思是,它編譯沒有警告。真的嗎?你修改的代碼,編譯爲32位而沒有警告?那將是一個驚喜。

+0

我已經給出了一個源代碼。這個源代碼在32位機器中沒有警告地編譯,但是當我將這些源代碼編譯成64位機器時,我在大多數中得到以下警告: 轉換爲來自不同大小整數的指針 我的任務是編譯64位沒有任何警告。爲此我做了一些像int類型改變到uintptr_t類型的改變。進行這些更改後,我最多收到以下警告: 警告:內聯失敗呼叫'tptp_StringCopy':呼叫不太可能,代碼大小會增加 請問您能否給我建議正確的方法? – thetna 2010-03-06 21:15:05

+2

聽着,如果你不明白爲什麼'unsigned int'與'unsigned int *'不一樣,那麼你需要更多的信息,而不是我在這裏可以提供的。我建議你先從這裏閱讀:http://www.ibm.com/developerworks/linux/library/l-port64.html?S_TACT=105AGX90&S_CMP=content – Cheeso 2010-03-06 21:24:09

+0

我已閱讀您在此處列出的鏈接:http:// www .ibm.com/developerworks/linux/library/l-port64.html?S_TACT = 105AGX90&S_CMP = content,我也參考以下鏈接: http://lists.windowmaker.info/dev/msg00081.html Mostly我遵循第二個鏈接。上述鏈接的方法是否不正確? – thetna 2010-03-06 21:38:59

1

unsigned int在64位系統上不能與uintptr_t互換。 intunsigned int在64位機器上仍然是32位值,但uintptr_t變爲64位類型。該類型被稱爲uintptr_t的原因是因爲該類型是與指針寬度相同的無符號整數值。這意味着在32位機器上,uintptr_t的寬度是32位,但在64位機器上的寬度是64位。

在代碼中,這意味着,與typedef變化,在64位機器NAT*是一個64位指針到一個64位的變量,但unsigned int*是一個64位指針到一個32位的可變。

clause_ComputeSplitFieldAddress仍然期待unsigned int*參數。

+0

可以喲請告訴,什麼是可互換的: typedef void * POINTER到64位系統? – thetna 2010-03-06 21:53:59

+0

它不會改變。指針類型在32位體系結構中始終爲32位寬,在64位體系結構中它們始終爲64位寬。 – 2010-03-06 22:05:34

+0

對於你的問題沒有一個簡單的答案。在某些情況下,您可能希望將'unsigned int'轉換爲'uintptr_t',在某些情況下您不會。沒有更多的上下文,沒有人能夠回答原始問題 - 理解具有類型NAT的變量中究竟包含了什麼。 – Cheeso 2010-03-06 22:20:27

1

我懷疑這裏的根本問題是,假設指針可以轉換爲32位整數類型而不會丟失。對於32位代碼,這是真的,對於64位代碼,它不是 - 指針是64位類型。這可能是最常見的32位到64位移植問題。

什麼是NAT實際打算是什麼?如果它是一個指向結構的不透明指針(在32位代碼中打扮成一個32位整數),最好將它聲明爲void *而不是uintptr_t。

1

沒有明顯的理由去改變POINTER typedef;在32位和64位(儘管32位版本佔用64位版本的一半空間)中,void指針仍然是空指針。只有當你濫用POINTER並試圖將其作爲某種你會遇到問題的整數來對待它時。

您不顯示clause_ComputeSplitFieldAddress的代碼,但顯然當函數帶有'NAT *'時,您無法傳遞'unsigned int'的地址;你將不得不查看它被調用的地方,並決定適當的操作來修復調用代碼 - 基本上,將相關的unsigned int變量改爲NAT變量。

對於tptp_StringCopy函數,也許你應該使用strdup() - 然後如果內存分配失敗,你可能不會立即崩潰。

您不會顯示與List_Cons()相關的警告,因此我們無法在此幫助。

通常,通過確保您不會在整數和指針之間進行類型雙擊,您可以處理許多32位至64位問題。當你必須使用uintptr_t(因此<inttypes.h>)。對特定typedef名稱使用變量類型定義時,嚴格使用<inttypes.h>中定義的打印和掃描格式。例如,使用

PRIXPTR 

格式化uintptr_t的值:

printf("0x%08" PRIXPTR "\n", ptr_as_int); 

這不會完全處理問題;它會處理很多他們。

如果想要了解未內聯的代碼,編譯器有權警告您。除了不要求內聯不能內聯的函數內聯外,你可以做的事情不多。