将 32 位 C 源代码移植到 64 位
我尝试移植到 64 位的 C 源代码在 32 位环境中运行时没有任何警告。当我在64位Linux环境下使用编译gcc(Ubuntu 4.4.1-4ubuntu9)4.4.1进行编译时,主要显示以下警告:
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 更改为较早的 int 或 unsigned int 的 uintptr_t 后,我遇到了大多数警告如下:
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;
如何摆脱这些警告?
The C source codes that I am trying to port into 64 bit runs without any warning in the 32 bit environment. When I compile in 64 bit Linux environment with the compile gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1, it shows the following warning mostly:
warning: cast to pointer from integer of different size
The above warning were the most. I used uintptr_t type and most of those warnings were removed. I could change the type int /unsigned int into 64 bit favorable using uintptr_t. But how can I change the following type to make compatible to 64 bit:
typedef void* POINTER;
I have changed the following code:
typedef unsigned int ABC;
into
typedef uintptr_t ABC
I got following warnings:
warning: passing argument 2 of ‘function’ from incompatible pointer type
note: expected ‘ABC *’ but argument is of type ‘unsigned int *’
Moreover, after changing type def into uintptr_t which were earlier either int or unsigned int, I am encountering most of the warnings as follows:
warning: inlining failed in call to ‘abc_StringCopy’: call is unlikely and code size would grow
The function tptp_StringCopy is as follows:
static __inline__ char* abc_StringCopy(void)
{
char *copy;
copy = (char*)Malloc(yyleng+1);
strcpy(copy, yytext);
return copy;
How can I get rid of these warnings?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 64 位系统上,
unsigned int
不能与uintptr_t
互换。int
和unsigned 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*
参数。unsigned int
is not interchangeable withuintptr_t
on 64-bit systems.int
andunsigned int
are still 32-bit values on 64-bit machines, butuintptr_t
becomes a 64-bit type. The reason that the type is calleduintptr_t
is because the type is an unsigned integer value that is the same width as a pointer. This means thatuintptr_t
is 32-bits wide on a 32-bit machine, but it becomes 64-bits wide on a 64-bit machine.In your code, this means that, with your
typedef
change, on 64-bit machinesNAT*
is a 64-bit pointer to a 64-bit variable, butunsigned int*
is a 64-bit pointer to a 32-bit variable.clause_ComputeSplitFieldAddress
is still expectingunsigned int*
parameters.我怀疑这里的根本问题是假设指针可以在 32 位整数类型之间进行转换而不会造成任何损失。对于 32 位代码来说这是正确的,对于 64 位代码则不然 - 指针是 64 位类型。这可能是最常见的 32 位到 64 位移植问题。
NAT 的实际用途是什么?如果它是指向结构的不透明指针(在 32 位代码中伪装成 32 位整数),则最好将其声明为 void* 而不是 uintptr_t。
I suspect the fundamental problem here is that something is assuming that a pointer can be cast to and from a 32-bit integer type without any loss. With 32-bit code this is true, with 64-bit code it is not - pointers are a 64-bit type. This is probably the most common 32-bit to 64-bit porting issue.
What is NAT actually intended to be? If it is an opaque pointer to a structure (dressed up as a 32-bit integer in 32-bit code), you might be best declaring it as a void* rather than a uintptr_t.
没有明显的理由改变 POINTER typedef; void 指针在 32 位和 64 位中仍然是 void 指针(尽管 32 位版本占用的空间是 64 位版本的一半)。只有当您滥用 POINTER 并尝试将其视为某种整数时,您才会遇到问题。
您没有显示 Clause_ComputeSplitFieldAddress 的代码,但显然当函数采用“NAT *”时,您无法传递“unsigned int”的地址;您必须查看它的调用位置并决定修复调用代码的适当操作 - 基本上,将相关的 unsigned int 变量更改为 NAT 变量。
对于 tptp_StringCopy 函数,也许您应该使用
strdup()
- 这样,如果内存分配失败,您可能不会立即崩溃。您没有显示与 List_Cons() 相关的警告,因此我们无法轻易提供帮助。
通常,您可以通过确保不在整数和指针之间进行类型双关来处理许多 32 位到 64 位问题。如果必须,请使用 uintptr_t(因此
)。当您具有特定 typedef 名称的变量类型定义时,请严格使用
中定义的打印和扫描格式。例如,使用格式化 uintptr_t 值:
这并不能解决所有问题;它将处理其中的很多问题。
如果编译器想要警告您未内联的代码,则有权警告您。除了不请求内联无法内联的函数之外,您无能为力。
There's no obvious reason to change the POINTER typedef; a void pointer is still a void pointer in both 32-bit and 64-bit (though the 32-bit version occupies half the space of the 64-bit version). It is only if you abuse POINTER and try to treat it as an integer of some sort that you will run into problems.
You don't show the code for clause_ComputeSplitFieldAddress, but clearly you cannot pass the address of an 'unsigned int' when the function takes a 'NAT *'; you will have to look at where it is called and decide on the appropriate action to fix the calling code - basically, change the relevant unsigned int variables into NAT variables.
For the tptp_StringCopy function, perhaps you should use
strdup()
- and then you probably won't get an immediate crash if the memory allocation fails.You don't show the warnings related to List_Cons(), so we can't readily help there.
Generally, you can deal with many of the 32-bit to 64-bit issues by ensuring that you don't do type punning between integers and pointers. When you must, use uintptr_t (and hence
<inttypes.h>
). And use the print and scan formats defined in<inttypes.h>
rigorously when you have variable type definitions for specific typedef names. For example, useto format a uintptr_t value:
This won't deal with every problem; it will deal with a lot of them.
The compiler is entitled to warn you if wants to about code that is not inlined. There isn't much you can do about that except not request inlining of functions that cannot be inlined.
我不太清楚情况,但似乎您将
unsigned int
更改为uintptr_t
。前者是一个unsigned int,后者是一个unsigned int指针。一般来说,这不是有效的替代。
另外,您说代码“在 32 位上运行时没有警告”,但 64 位编译会给您警告。但它是否在没有警告的情况下运行并不重要。也许你的意思是,它编译时没有警告。这是真的吗?您修改的代码编译为 32 位时没有警告吗?那将是一个惊喜。
I'm not exactly clear on the situation, but it seems that You changed
unsigned int
touintptr_t
. The former is an unsigned int, the latter is an unsigned int pointer.In general, that's not a valid substitution to make.
Also, you said the code "runs without warning on 32 bit" but compilation for 64-bit gives you warnings. But it really doesn't matter whether it runs without warning. Maybe you mean, it compiles without warnings. Is that true? The code you've modified, compiles for 32-bit without warning? That would be a surprise.