C++风格_64 位下的可移植性

代码应该对 64 位和 32 位系统友好. 处理打印, 比较, 结构体对齐时应切记:

  • 对于某些类型, printf() 的指示符在 32 位和 64 位系统上可移植性不是很好. C99 标准定义了一些可移植的格式化指示符. 不幸的是, MSVC 7.1 并非全部支持, 而且标准中也有所遗漏, 所以有时我们不得不自己定义一个丑陋的版本 (头文件 inttypes.h 仿标准风格):
// printf macros for size_t, in the style of inttypes.h
#ifdef _LP64
#define __PRIS_PREFIX "z"
#else
#define __PRIS_PREFIX
#endif
// Use these macros after a % in a printf format string
// to get correct 32/64 bit behavior, like this:
// size_t size = records.size();
// printf("%"PRIuS"\n", size);
#define PRIdS __PRIS_PREFIX "d"
#define PRIxS __PRIS_PREFIX "x"
#define PRIuS __PRIS_PREFIX "u"
#define PRIXS __PRIS_PREFIX "X"
#define PRIoS __PRIS_PREFIX "o"
类型 不要使用 使用 备注
void * (或其他指针类型) %lx %p
int64_t %qd, %lld %”PRId64”
uint64_t %qu, %llu, %llx %”PRIu64”, %”PRIx64”
size_t %u %”PRIuS”, %”PRIxS” C99 规定 %zu
ptrdiff_t %d %”PRIdS” C99 规定 %zd

注意 PRI* 宏会被编译器扩展为独立字符串. 因此如果使用非常量的格式化字符串, 需要将宏的值而不是宏名插入格式中. 使用 PRI* 宏同样可以在 % 后包含长度指示符. 例如, printf(“x = %30”PRIuS”\n”, x) 在 32 位 Linux 上将被展开为 printf(“x = %30” “u” “\n”, x), 编译器当成 printf(“x = %30u\n”, x) 处理 (Yang.Y 注: 这在 MSVC 6.0 上行不通, VC 6 编译器不会自动把引号间隔的多个字符串连接一个长字符串).

  • 记住 sizeof(void *) != sizeof(int). 如果需要一个指针大小的整数要用 intptr_t.
  • 你要非常小心的对待结构体对齐, 尤其是要持久化到磁盘上的结构体 (Yang.Y 注: 持久化 - 将数据按字节流顺序保存在磁盘文件或数据库中). 在 64 位系统中, 任何含有 int64_t/uint64_t 成员的类/结构体, 缺省都以 8 字节在结尾对齐. 如果 32 位和 64 位代码要共用持久化的结构体, 需要确保两种体系结构下的结构体对齐一致. 大多数编译器都允许调整结构体对齐. gcc 中可使用 attribute((packed)). MSVC 则提供了 #pragma pack() 和 __declspec(align()) (YuleFox 注, 解决方案的项目属性里也可以直接设置).
  • 创建 64 位常量时使用 LL 或 ULL 作为后缀, 如:
int64_t my_value = 0x123456789LL;
uint64_t my_mask = 3ULL << 48;
  • 如果你确实需要 32 位和 64 位系统具有不同代码, 可以使用 #ifdef _LP64 指令来切分 32/64 位代码. (尽量不要这么做, 如果非用不可, 尽量使修改局部化)

你可能感兴趣的:(编程风格)