将C源代码移植到32位到64位

时间:2010-03-06 20:13:54

标签: c 32bit-64bit gcc-warning

我试图在32位环境中没有任何警告的情况下尝试移植到64位的C源代码。当我使用编译gcc(Ubuntu 4.4.1-4ubuntu9)4.4.1在64位Linux环境中编译时,它主要显示以下警告:

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 *’

此外,在将类型def更改为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;

如何摆脱这些警告?

4 个答案:

答案 0 :(得分:2)

在64位系统上,

unsigned intuintptr_t不可互换。 intunsigned int在64位计算机上仍为32位值,但uintptr_t成为64位类型。类型被称为uintptr_t的原因是因为类型是无符号整数值,其宽度与指针相同。这意味着uintptr_t在32位机器上为32位宽,但在64位机器上为64位宽。

在您的代码中,这意味着,在typedef更改时,在64位计算机上NAT*是指向64位变量的64位指针,但unsigned int*是一个指向32位变量的64位指针。

clause_ComputeSplitFieldAddress仍然期待unsigned int*个参数。

答案 1 :(得分:1)

我怀疑这里的根本问题是某些东西假设一个指针可以转换为32位整数类型而不会丢失。使用32位代码确实如此,64位代码不是 - 指针是64位类型。这可能是最常见的32位到64位移植问题。

NAT实际上是什么意思?如果它是一个指向结构的不透明指针(在32位代码中打扮成32位整数),则最好将其声明为void *而不是uintptr_t。

答案 2 :(得分:1)

没有明显的理由改变POINTER typedef; void指针仍然是32位和64位的空指针(尽管32位版本占用64位版本的一半空间)。只有当你滥用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);

这不会解决所有问题;它将处理很多它们。

如果想要了解未内联的代码,编译器有权发出警告。除了没有请求内联无法内联的函数之外,你无能为力。

答案 3 :(得分:-1)

我对情况并不十分清楚,但您似乎已将unsigned int更改为uintptr_t。前者是unsigned int,后者是unsigned int 指针

一般来说,这不是一个有效的替代品。

另外,你说代码“在32位没有警告的情况下运行”但是64位的编译会给你警告。但它是否在没有警告的情况下运行并不重要。也许你的意思是,它编译没有警告。真的吗?您修改过的代码在没有警告的情况下编译为32位?那将是一个惊喜。