• 对于某些类型, printf() 的指示符在 32 位和 64 位系统上可移植性不是很好. C99 标准定义了一些可移植的格式化指示符. 不幸的是, MSVC 7.1 并非全部支持, 而且标准中也有所遗漏, 所以有时我们不得不自己定义一个丑陋的版本 (头文件 inttypes.h 仿标准风格): ```cpp // 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”

  1. | **类型** | **不要使用** | **使用** | **备注** |
  2. | --- | --- | --- | --- |
  3. | void * (或其他指针类型) | %lx | %p | |
  4. | int64_t | %qd, %lld | %"PRId64" | |
  5. | uint64_t | %qu, %llu, %llx | %"PRIu64", %"PRIx64" | |
  6. | size_t | %u | %"PRIuS", %"PRIxS" | C99 规定 %zu |
  7. | ptrdiff_t | %d | %"PRIdS" | C99 规定 %zd |
  8. 注意 `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 编译器不会自动把引号间隔的多个字符串连接一个长字符串).
  9. - 记住 `sizeof(void *) != sizeof(int)`. 如果需要一个指针大小的整数要用 `intptr_t`.
  10. - 你要非常小心的对待结构体对齐, 尤其是要持久化到磁盘上的结构体 (Yang.Y 注: 持久化 - 将数据按字节流顺序保存在磁盘文件或数据库中). 64 位系统中, 任何含有 `int64_t`/`uint64_t` 成员的类 / 结构体, 缺省都以 8 字节在结尾对齐. 如果 32 位和 64 位代码要共用持久化的结构体, 需要确保两种体系结构下的结构体对齐一致. 大多数编译器都允许调整结构体对齐. gcc 中可使用 `__attribute__((packed))`. MSVC 则提供了 `#pragma pack()` `__declspec(align())` (YuleFox 注, 解决方案的项目属性里也可以直接设置).
  11. - 创建 64 位常量时使用 LL ULL 作为后缀, 如:
  12. ```cpp
  13. int64\_t my\_value \= 0x123456789LL;
  14. uint64\_t my\_mask \= 3ULL << 48;
  • 如果你确实需要 32 位和 64 位系统具有不同代码, 可以使用 #ifdef _LP64 指令来切分 32/64 位代码. (尽量不要这么做, 如果非用不可, 尽量使修改局部化)

注意:添加头文件:

  1. #include <stdint.h>
  2. #include <inttypes.h>

https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/others/#id12