c++ - %ld 格式转换以实现便携性

标签 c++ x86 printf 32bit-64bit 16-bit

在添加对 Linux 64 的支持之前,这很容易。几乎所有数据都被声明为 int 或来自 BYTE、WORD 和 DWORD 的类型定义:

typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned long   DWORD;

添加 64 位 gcc 支持后,DWORD 需要稍微调整以保持 32 位值,因为它代表存储的数据:

// to compile DWORDs as 32 bits on 64-bit machines:
#if __x86_64__
 typedef unsigned int    DWORD;
#else
 typedef unsigned long   DWORD;
#endif

这在所有环境中都运行良好:

DWORD   data;
printf ("%lu", data);

但是,gcc -Wall 现在会提示格式转换:

warning: format ‘%ld’ expects argument of type ‘long int’, but argument
         1 has type ‘DWORD {aka unsigned int}’ [-Wformat]

由于这段代码的大量格式化——数千行输出格式化——我宁愿不改造特定类型的格式化程序。类似的问题是 answered by using the z modifier :

printf ("%zu", data);

但这使得 MSDOS 和 Win32 控制台上的 Turbo C 做了一些奇怪的事情:它显示转换规范 %zu 作为输出而不是转换任何东西。

是否有更简洁的方法来处理类型的可变性,使其符合 printf 的粒度和基本数据类型?

最佳答案

我认为你最不坏的可用选择是从概念上借用 <inttypes.h> :

#ifdef _LP64
#define PRIdword  "d"
#define PRIudword "u"
#else
#define PRIdword  "ld"
#define PRIudword "lu"
#endif

然后

DWORD data;
printf("%"PRIdword, data);

这利用了所有 C90 兼容的编译器都应该支持的字符串常量连接。请注意,要测试的正确宏是 _LP64 , 不是 __x86_64__ ;这样,当您转到其他 LP64 系统或 Linux/x86-64(32 位指针,宽寄存器)的 Shiny 新“x32”模式时,它就会正常工作。

投资大规模转换为 <stdint.h> 可能不是一个坏主意类型,但这不会让你摆脱这种事情,你只是在写

int32_t data;
printf("%"PRId32, data);

相反,据我所知大多数 Windows 编译器仍然没有<inttypes.h> ,感叹。

如果您想知道,%不在宏内,因此您可以根据需要放入格式调整器:

printf("%-32"PRIdword, data);

关于c++ - %ld 格式转换以实现便携性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16949445/

相关文章:

C++ : Why I can't print a const char* with sprintf?

c++ - 直接复制与虚拟复制构造函数(克隆函数)

c++ - 模板多态可以代替OO多态吗?

c++ - 在CListCtrl上设置排序指示器正在清除列标题

c# - 为什么 Box2D/Farseer EdgeShape 定义了 4 个顶点?

c - printf() 无格式字符串打印字符和整数数组 --> 垃圾

JavaScript 等价于 printf/String.Format

c++ - 为什么 C++ 中的这个 lambda 包含每个引用?

c++ - 如何反转 __m128 类型变量?

c++ - 在编译时检测处理器是否有 RDTSCP