64位系统编程注意事项
2) int 32 位, long 64 位, 指针 64位, char 8, short 16
3) 如何与32位系统通讯:
a) 使用32位的数据类型
系统头文件<sys/types.h>和<inttypes.h>中包含的有助于应用程序对于32位和64位均安全的常量、宏、和派生类型。
转换为LP64知道原则:
请勿假设int和指针的长度相同。
请勿假设int和long的长度相同。
符号扩展
1) 整数提升:无论有无符号,都可以在调用类型为int的表达式中使用char,short,枚举类型或者位字段。如果int可以支持初始类型的所有可能,则值会转换为int类型。否则,转换为unsigned int类型。
2) 带符号整数和无符号整数之间的转换:将带符号的整数提升为同一类的或者更长类的无符号整数时,该整数首先提升为更长类型的带符号相同值,然后转换为无符号值。
两个有符号整数相加的结果是一个有符号整数。
int 和 long 类型的两个数相加,结果是一个 long 类型的数。
一个操作数是无符号整数和另外一个操作数是有符号整数,那么表达式的结果就是无符号整数。
int 和 doubule 类型的两个数相加,结果是一个 double 类型的数。
使用指针运算,而不是地址运算:通常指针运算都是独立于数据模型的,而地址运算则可能不是,因此指针运算比地址运算更好。
对结构重新压缩:
由于long是64位,因此,尽量将long型的放在结构体开头或者结尾。
检查联合类型:
因为其字段的长度可能在ILP32和LP64数据模型之间可能会发生变化。
typedef union{double d; long l[2]}
应当为
typedef union{double d; int l[2]}
指定数据类型:
在常量表达式后面增加{u,U,l,L}的某些组合,可以指定类型。
int i = 32;
long j = 1 << I; -à long j = 1L << I;
注意隐士声明:
在某些编译模式下,编译器可能会假设针对在模块中使用却未在外部定义或者声明的任何函数或者变量,使用int类型。
Sizeof是unsigned long
在LP64环境中,sizeof的有效类型是site_t,该类型是unsigned long。
使用强制类型转换说明意图:
检查格式字符串转换操作:
对于类型为long或指针的参数,可能需要更改printf,sprintf,scanf,sscanf的格式字符串。指针要转换为%p,long型参数转换为添加一个l在格式字符串前面。
检查直接使用long类型是否仍有意义:
例如:pid_t在32为环境中是long类型,在64为系统中是int类型。
对显示32位与64位原型使用#ifdef
某些情况下,一个接口存在对特定的32位和64位版本是不可避免的。可以通过头文件使用_LP64或_ILP32功能测试宏来区分这些版本。
LD_LIBRARY_PATH
可以将32位的lib和64位的lib的路径都设置到这个变量中,也可以将64位的lib路径设置到LD_LIBRARY_PATH_64中。
高级主题
指令大小仍然是32位的。
整数乘除可以完全在硬件中实现。
结构的传递和返回以不同的方式实现。小型数据结构和某些浮点参数可以直接在寄存器中传递。
所有数据类型现在都与其长度对齐。
系统中存在两种不同的库,32位的库和64位的库。
Ioctl或者ipc机制的接口,通过对这些接口仔细进行编码,并且谨慎地使用#Pragma pack或_Pack指令,可避免对其问题。
进程间通讯
使用相同长度的类型。
64位应用程序的优点:
针对64位值更高效地执行算术和逻辑运算。
运算过程使用全寄存器宽度、全寄存器集合新指令。
值得参数传递效率更高。
小型数据结构和浮点数值得参数传递效率更高。
提供了额外的整数寄存器和浮点寄存器。
对于amd64,提供了PC相关寻址模式,从而可提高位置无关代码的执行效率。
缺点:
64位应用程序需要更多的栈空间才能容纳更大的寄存器。
由于使用了更大的指针,因此应用程序需要更大的高速缓存。
64位应用程序不能运行在32位平台上。
EOVERFLOW的含义:
许多32位系统调用在遇到64位内核中的大对象时,都会返回EOVERFLOW,由于daddr_t,dev_t,time_t,及其派生类型struct timeval和timespec_t现在包含的64位值,因此可能意味着32位应用程序会遇到更多的EOVERFLOW返回值。
谨慎使用ioctl
请考虑使用两个icotl调用:一个用来处理32位值(IOP32)的指针,另一个用来处理长值(IOPLONG)的指针。
int a,d;
long b;
if (icotl(d, IOP32, &b) == -1)
if (icotl(d, IOPLONG, &a) == -1)
编译此代码并将其作为32位应用程序的一部分运行时,这两个ioctl调用均可正常工作。
但是,编译作为64位应用程序时,这两个调用均可返回。但是,这两个均无法正常工作。第一个,传递的容量太大,其结果和大端,小端字节序有关。第二个,则会溢出,覆盖栈上的附近的地址的内容。
派生类型更改
例如:
#if defined(_LP64)
Typedef ulong_t size_t;
#else
Typedef uint_t size_t;
#endif
如何确定系统运行的是32位还是64位的?
RedHeat和CentOS
file /bin/ls 使用file察看任何一个文件在/bin路径下都可以,显示结果为:
[root@localhost bin]# file date
date: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
[root@hfgs126 bin]# file wbxgs
wbxgs: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.4.0, dynamically linked (uses shared libs), not stripped
1302

被折叠的 条评论
为什么被折叠?



