Pie*_*BdR 77 c++ 64-bit gcc casting 32-bit
我正在尝试将现有代码调整为64位机器.主要问题是在一个函数中,前一个编码器使用void*参数,该参数在函数本身中转换为合适的类型.一个简短的例子:
void function(MESSAGE_ID id, void* param)
{
if(id == FOO) {
int real_param = (int)param;
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
当然,在64位机器上,我收到错误:
error: cast from 'void*' to 'int' loses precision
Run Code Online (Sandbox Code Playgroud)
我想纠正这个问题,以便它仍然可以在32位机器上运行并且尽可能干净.任何的想法 ?
Ale*_*lex 79
我会说这是现代的C++方式.
#include <cstdint>
void *p;
auto i = reinterpret_cast<std::uintptr_t>(p);
Run Code Online (Sandbox Code Playgroud)
编辑:
所以将指针存储为整数的正确方法是使用uintptr_t
或intptr_t
类型.(另请参阅C99的 cppreference 整数类型).
这些类型在<stdint.h>
C99和std
C++ 11 的命名空间中定义<cstdint>
(请参阅C++的整数类型).
C++ 11(及以后)版本
#include <cstdint>
std::uintptr_t i;
Run Code Online (Sandbox Code Playgroud)
C++ 03版
extern "C" {
#include <stdint.h>
}
uintptr_t i;
Run Code Online (Sandbox Code Playgroud)
C99版
#include <stdint.h>
uintptr_t i;
Run Code Online (Sandbox Code Playgroud)
在C中只有一个强制转换,并且在C++中使用C强制转换是不受欢迎的(所以不要在C++中使用它).在C++中有不同的演员阵容.reinterpret_cast
是这次转换的正确演员(另见此处).
C++ 11版
auto i = reinterpret_cast<std::uintptr_t>(p);
Run Code Online (Sandbox Code Playgroud)
C++ 03版
uintptr_t i = reinterpret_cast<uintptr_t>(p);
Run Code Online (Sandbox Code Playgroud)
C版
uintptr_t i = (uintptr_t)p; // C Version
Run Code Online (Sandbox Code Playgroud)
Mil*_*kov 66
使用intptr_t
和uintptr_t
.
为确保以便携方式定义,您可以使用以下代码:
#if defined(__BORLANDC__)
typedef unsigned char uint8_t;
typedef __int64 int64_t;
typedef unsigned long uintptr_t;
#elif defined(_MSC_VER)
typedef unsigned char uint8_t;
typedef __int64 int64_t;
#else
#include <stdint.h>
#endif
Run Code Online (Sandbox Code Playgroud)
只需将其放在某个.h文件中,并将其包含在您需要的任何位置.
或者,你可以下载微软的版本stdint.h
从文件在这里,或者使用从便携式一个在这里.
Ric*_*den 41
'size_t'和'ptrdiff_t'需要与您的架构相匹配(无论它是什么).因此,我认为不应该使用'int',而应该能够使用'size_t',它在64位系统上应该是64位类型.
这个讨论unsigned int vs size_t更详细一些.
有几个答案指出uintptr_t
并#include <stdint.h>
作为"解决方案".也就是说,我建议,答案的一部分,但不是整个答案.您还需要查看使用FOO的消息ID调用函数的位置.
考虑这段代码和编译:
$ cat kk.c
#include <stdio.h>
static void function(int n, void *p)
{
unsigned long z = *(unsigned long *)p;
printf("%d - %lu\n", n, z);
}
int main(void)
{
function(1, 2);
return(0);
}
$ rmk kk
gcc -m64 -g -O -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith \
-Wcast-qual -Wstrict-prototypes -Wmissing-prototypes \
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE kk.c -o kk
kk.c: In function 'main':
kk.c:10: warning: passing argument 2 of 'func' makes pointer from integer without a cast
$
Run Code Online (Sandbox Code Playgroud)
您将观察到调用位置(in main()
)存在问题- 将整数转换为没有强制转换的指针.您将需要分析您function()
的所有用法,以了解如何将值传递给它.function()
如果写入调用,我的内部代码将起作用:
unsigned long i = 0x2341;
function(1, &i);
Run Code Online (Sandbox Code Playgroud)
由于您的编写方式可能不同,因此需要查看调用函数的点,以确保使用显示的值是有意义的.别忘了,你可能会发现一个潜在的错误.
此外,如果您要格式化void *
参数的值(转换后),请仔细查看<inttypes.h>
标题(而不是stdint.h
- inttypes.h
提供服务stdint.h
,这是不寻常的,但C99标准说[标题]标题<inttypes.h>
包括标题<stdint.h>
和通过托管实现提供的附加功能扩展它,并在格式字符串中使用PRIxxx宏.
此外,我的注释严格适用于C而不是C++,但您的代码位于C++的子集中,可以在C和C++之间移植.我的评论适用的机会是公平的.
归档时间: |
|
查看次数: |
145701 次 |
最近记录: |