- 对于某些类型,
printf()
的指示符在 32 位和 64 位系统上可移植性不是很好. C99 标准定义了一些可移植的格式化指示符. 不幸的是, MSVC 7.1 并非全部支持, 而且标准中也有所遗漏, 所以有时我们不得不自己定义一个丑陋的版本 (头文件inttypes.h
仿标准风格): ```cpp // printf macros for size_t, in the style of inttypes.hifdef _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 作为后缀, 如:
```cpp
int64\_t my\_value \= 0x123456789LL;
uint64\_t my\_mask \= 3ULL << 48;
- 如果你确实需要 32 位和 64 位系统具有不同代码, 可以使用
#ifdef _LP64
指令来切分 32/64 位代码. (尽量不要这么做, 如果非用不可, 尽量使修改局部化)
注意:添加头文件:
#include <stdint.h>
#include <inttypes.h>
https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/others/#id12