64位下C程序的可移植性
qq:9611153 微信lgs9611153
时间:2012/11/28 9:54:03
转载,64位下C程序的可移植性(64-bit Portability):
C代码在64位和32位的系统中,原则上应该都比较友好,尤其对于输出、比较、结构对齐(structure alignment)来说:
1) printf()指定的一些类型在32位和64位系统上可移植性不是很好,C99标准定义了一些可移植的格式。
不幸的是,MSVC 7.1并非全部支持,而且标准中也有所遗漏。所以有时我们就不得不自己定义丑陋的版本(使用标准风格要包含文件inttypes.h):
Include the standard header <inttypes.h> to define a type, several functions, and numerous macros for fine control over the conversion of integers. Note that the definitions shown for the macros are merely representative -- they can vary among implementations.
注意宏PRI*会被编译器扩展为独立字符串,因此如果使用非常量的格式化字符串,需要将宏的值而不是宏名插入格式中,在使用宏PRI*时同样可以在%后指定长度等信息。例如,printf("x = %30"PRIuS"n", x)在32位Linux上将被扩展为printf("x = %30" "u" "n", x),编译器会处理为printf("x = %30un", x)。
2) 记住sizeof(void *) != sizeof(int),如果需要一个指针大小的整数要使用intptr_t。
3) 需要对结构对齐加以留心,尤其是对于存储在磁盘上的结构体。
在64位系统中,任何拥有int64_t/uint64_t成员的类/结构体将默认被处理为8字节对齐。
如果32位和64位代码共用磁盘上的结构体,需要确保两种体系结构下的结构体的对齐一致。
大多数编译器提供了调整结构体对齐的方案。
gcc中可使用__attribute__((packed)),MSVC提供了#pragma pack()和__declspec(align())。
4) 创建64位常量时使用LL或ULL作为后缀,如:
int64_t my_value = 0x123456789LL;
uint64_t my_mask = 3ULL << 48;5)
如果你确实需要32位和64位系统具有不同代码,可以在代码变量前使用。(尽量不要这么做,使用时尽量使修改局部化)。
所需资源:
简述(技术,材料,环境)
测试打印64位整数:
static BOOL printlogA(const CHAR *format_str,...) { #define LOG_LENGTH 2048 CHAR m_lpMsgInfoA[LOG_LENGTH]; CHAR* lpMsgInfo = m_lpMsgInfoA;
int lenMsg = 0; va_list args; va_start( args, format_str ); int len = _vscprintf( format_str, args ) + 1; if (len < LOG_LENGTH) { lenMsg = vsprintf_s(lpMsgInfo,len,format_str,args);//有异常 } va_end(args);
return TRUE; }
int _tmain(int argc, _TCHAR* argv[]) { int Hex1 = 0xF0F0; int Hex2 = 0xF1F0;
int Diff = Hex1^Hex2;
typedef signed long SInt64; SInt64 xx = 100; //_tprintf(_T("send = %qd"),xx);//显示send = qd //说明不支持%qd //printlogA("--- Options transaction time ms = %qd ---\n",100);
_tprintf(_T("send = %lld"),xx);//显示send = 100 printlogA("--- Options transaction time ms = %lld ---\n",100);
system("pause"); return 0; }
|