wal*_*lyk 4 c++ x86 printf 16-bit 32bit-64bit
我有一个代码库,旨在在没有警告的情况下进行编译,并在多种架构上运行而不会出现任何故障,所有 x86:MSDOS、Windows 32 控制台模式、Windows 32 GUI 模式、Linux 32 和 Linux 64。
\n\n在添加对 Linux 64 的支持之前,这很容易。几乎所有数据都被声明为int
BYTE、WORD 和 DWORD 的类型定义:
typedef unsigned char BYTE;\ntypedef unsigned short WORD;\ntypedef unsigned long DWORD;\n
Run Code Online (Sandbox Code Playgroud)\n\n添加 64 位 gcc 支持后,DWORD 需要进行一些调整才能保持 32 位值,因为它表示存储的数据:
\n\n// to compile DWORDs as 32 bits on 64-bit machines:\n#if __x86_64__\n typedef unsigned int DWORD;\n#else\n typedef unsigned long DWORD;\n#endif\n
Run Code Online (Sandbox Code Playgroud)\n\n这在所有环境下都运行良好:
\n\nDWORD data;\nprintf ("%lu", data);\n
Run Code Online (Sandbox Code Playgroud)\n\n但是,gcc -Wall
现在抱怨格式转换:
warning: format \xe2\x80\x98%ld\xe2\x80\x99 expects argument of type \xe2\x80\x98long int\xe2\x80\x99, but argument\n 1 has type \xe2\x80\x98DWORD {aka unsigned int}\xe2\x80\x99 [-Wformat]\n
Run Code Online (Sandbox Code Playgroud)\n\n由于此代码进行了广泛的格式化(数千行输出格式化),我宁愿不改进特定于类型的格式化程序。使用z
修饰符回答了类似的问题:
printf ("%zu", data);\n
Run Code Online (Sandbox Code Playgroud)\n\n但这使得 MSDOS 和 Win32 控制台上的 Turbo C 做了一些奇怪的事情:它将转换规范显示%zu
为输出,而不是转换任何内容。
是否有一种更清晰的方法来以符合 printf 和基本数据类型的方式处理类型的可变性?
\n我认为你最不坏的可用选择是从概念上借用<inttypes.h>
:
#ifdef _LP64
#define PRIdword "d"
#define PRIudword "u"
#else
#define PRIdword "ld"
#define PRIudword "lu"
#endif
Run Code Online (Sandbox Code Playgroud)
进而
DWORD data;
printf("%"PRIdword, data);
Run Code Online (Sandbox Code Playgroud)
这利用了字符串常量连接,所有 C90 兼容编译器都应该支持。请注意,要测试的正确宏是_LP64
, 不是__x86_64__
; 这样,当您移植到其他一些 LP64 系统或 Linux/x86-64 的闪亮新“x32”模式(32 位指针、宽寄存器)时,它就会正常工作。
投资对类型的批量转换可能不是一个坏主意<stdint.h>
,但这不会让你摆脱这种事情,你只是在写
int32_t data;
printf("%"PRId32, data);
Run Code Online (Sandbox Code Playgroud)
相反,据我所知,大多数 Windows 编译器仍然没有<inttypes.h>
,叹息。
如果您想知道,它%
不在宏内部,因此您可以根据需要放入格式调整器:
printf("%-32"PRIdword, data);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14026 次 |
最近记录: |