linux驱动编写32位与64位设备注意事项
来源:互联网 发布:都市小说改编的网络剧 编辑:程序博客网 时间:2024/06/05 07:27
数据类型问题
Linux系统32位与64位GCC编译器基本数据类型长度对照表
sizeof(char)=1
sizeof(double)=8
sizeof(float)=4
sizeof(int)=4
sizeof(short)=2
sizeof(long)=4
sizeof(long long)=8
sizeof(long double)=12
sizeof(complex long double)=24
GCC 64位
sizeof(char)=1
sizeof(double)=8
sizeof(float)=4
sizeof(int)=4
sizeof(short)=2
sizeof(long)=8
sizeof(long long)=8
sizeof(long double)=16
sizeof(complex long double)=32
64位操作系统编码规范
一、Linux及Windows主要类型字节长度
类型
32位
64位
short
2
2
int
4
4
long
4
Linux:8 Windows:4
size_t
4
8
void *(及其它指针)
4
8
time_t
8
8
float
4
4
double
8
8
二、不允许使用long型;
三、不允许把int强制转换为指针,反之亦然;下面是错误的:int i = (int )ptr; 或: void *ptr = (void *)s32Tmp;
四、不允许在不同类型的指针(有继承关系除外)进行强制转换,如:int *ipTmp; time_t *tpTmp = *ipTmp;是错误的;
五、强烈建议使用带长度的类型,如:SInt32/UInt64等;
六、必须使用%p打印指针,如printf(“this[%p]\n”,this);
七、强烈建议不要采用scanf,scanf非常危险,Format和参数类型不一致时,非常容易导致越界写。如果必须使用,则必须认真区别32和64位的操作系统整数长度的差别,需要时,分别针对32和64位编写代码;
八、如果编写动态链接库,必须加上–fPIC编译选项;
九、采用GCC编译器时,必须使用-Wlong-long、-Wformat -Wpointer-arith 来发现 64 位编译问题,并关注相关警告信息;
十、编译器指示宏定义
宏定义
描述
__linux__
Linux操作系统,与Windows及其它类型操作系统区别
i386
Linux操作系统,32位x86架构
x86-64(注意是减号)
Linux操作系统,64位x86架构
_WINDOWS_
Windows操作系统,与其它操作系统区别
_X86_
Windows操作系统,32位x86架构
__MacOSX__
Apple OSX
_posix_
符合POSIX规范,类Unix操作系统,包括Linux/IBM AIX/HPUS/Sun Solaris/Apple MacOSX等
十一、 宏使用说明:
l 我们的代码要求同时支持32位和64位版本;
l 尽量不要使用与架构相关的宏,如i386/ x86-64/_X86_/Win32等,在同一操作系统中,API一般与架构无关,这样可以让代码具有良好的移植性;
l 我们的软件主要在类Unix(符合POSIX规范,包括Linux)和Windows下运行,优先使用_posix_作为区别非windows操作系统;
l 如果对准备使用的类UNIX下系统调用(API)是否支持其它操作系统没有把握,可使用_posix_加以标记,待日后移植到其它操作系统时,再测试或修改;
Linux 64 位体系结构
不幸的是,C 编程语言并没有提供一种机制来添加新的基本数据类型。因此,提供 64 位的寻址和整数运算能力必须要修改现有数据类型的绑定或映射,或者向 C 语言中添加新的数据类型。
表 1. 32 位和 64 位数据模型
数据对象的大小。编译器按照自然边界对数据类型进行对齐;换而言之,32 位的数据类型在 64 位系统上要按照 32 位边界进行对齐,而 64 位的数据类型在 64 位系统上则要按照 64 位边界进行对齐。这意味着诸如结构或联合之类的数据对象的大小在 32 位和 64 位系统上是不同的。
基本数据类型的大小。通常关于基本数据类型之间关系的假设在 64 位数据模型上都已经无效了。依赖于这些关系的应用程序在 64 位平台上编译也会失败。例如,sizeof (int) = sizeof (long) = sizeof (pointer) 的假设对于 ILP32 数据模型有效,但是对于其他数据模型就无效了。
总之,编译器要按照自然边界对数据类型进行对齐,这意味着编译器会进行 “填充”,从而强制进行这种方式的对齐,就像是在 C 结构和联合中所做的一样。结构或联合的成员是根据最宽的成员进行对齐的。清单 1 对这个结构进行了解释。
清单 1. C 结构
struct test {int i1;double d;int i2;long l;}
表 2 给出了这个结构中每个成员的大小,以及这个结构在 32 位系统和 64 位系统上的大小。
表 2. 结构和结构成员的大小
注意,在一个 32 位的系统上,编译器可能并没有对变量 d 进行对齐,尽管它是一个 64 位的对象,这是因为硬件会将其当作两个 32 位的对象进行处理。然而,64 位的系统会对 d 和 l 都进行对齐,这样会添加两个 4 字节的填充。
从 32 位系统移植到 64 位系统
本节介绍如何解决一些常见的问题:
声明表达式赋值数字常数Endianism类型定义位移字符串格式化函数参数
声明
要想让您的代码在 32 位和 64 位系统上都可以工作,请注意以下有关声明的用法:
根据需要适当地使用 “L” 或 “U” 来声明整型常量。
确保使用无符号整数来防止符号扩展的问题。
如果有些变量在这两个平台上都需要是 32 位的,请将其类型定义为 int.如果有些变量在 32 位系统上是 32 位的,在 64 位系统上是 64 位的,请将其类型定义为 long.为了对齐和性能的需要,请将数字变量声明为 int 或 long 类型。不要试图使用 char 或 short 类型来保存字节。
将字符指针和字符字节声明为无符号类型的,这样可以防止 8 位字符的符号扩展问题。
表达式
在 C/ 中,表达式是基于结合律、操作符的优先级和一组数学计算规则的。要想让表达式在 32 位和 64 位系统上都可以正确工作,请注意以下规则:
两个有符号整数相加的结果是一个有符号整数。
int 和 long 类型的两个数相加,结果是一个 long 类型的数。
如果一个操作数是无符号整数,另外一个操作数是有符号整数,那么表达式的结果就是无符号整数。
int 和 doubule 类型的两个数相加,结果是一个 double 类型的数。此处 int 类型的数在执行加法运算之前转换成 double 类型。
赋值
由于指针、int 和 long 在 64 位系统上大小不再相同了,因此根据这些变量是如何赋值和在应用程序中使用的,可能会出现问题。下面是有关赋值的一些技巧:
不要使用 int 和 long 类型,因为这可能会导致高位数字被截断。例如,不要做下面的事情:
int i;long l;i = l;
不要使用 int 类型来指针。下面这个例子在 32 位系统上可以很好地工作,但是在 64 位系统上会失败,这是因为 32 位整数无法存放 64 位的指针。例如,不要做下面的事情:
unsigned int i, *ptr;i = (unsigned) ptr;
不要使用指针来存放 int 类型的值。例如,不要做下面的事情;
int *ptr;int i;ptr = (int *) i;
如果在表达式中混合使用无符号和有符号的 32 位整数,并将其赋值给一个有符号的 long 类型,那么将其中一个操作数转换成 64 位的类型。这会导致其他操作数也被转换成 64 位的类型,这样在对表达式进行赋值时就不需要再进行转换了。另外一种解决方案是对整个表达式进行转换,这样就可以在赋值时进行符号扩展。例如,考虑下面这种用法可能会出现的问题:
long n;int i = -2;unsigned k = 1;n = i + k;
从数学计算上来说,上面这个黑体显示的表达式的结果应该是 -1 。但是由于表达式是无符号的,因此不会进行符号扩展。解决方案是将一个操作数转换成 64 位类型(下面的第一行就是这样),或者对整个表达式进行转换(下面第二行):
n = (long) i + k;n = (int) (i + k);
- linux驱动编写32位与64位设备注意事项
- linux驱动编写32位与64位设备注意事项
- linux驱动编写32位与64位设备部分注意事项
- RegOpenKeyEx在64位与32位系统编程注意事项
- 32位与64位编程注意事项总结
- 32位与64位编程注意事项总结
- 简图记录-linux驱动32位移植64位
- 学习windows驱动(32位与64位兼容)
- 32位移植到64位 注意事项
- 32位USB设备驱动工程移植64位编译(用到vdw_wdm.lib)
- 32位与64位
- Linux系统32位与64位数据类型长度比较
- Linux系统32位与64位数据类型长度比较
- Linux系统32位与64位数据类型长度比较
- 64位linux c语言开发注意事项
- 64位linux c语言开发注意事项
- 编写Linux设备驱动
- 在Visual Studio下编写64位应用程序的注意事项
- VoIP协议栈
- Combining Sketch and Tone for Pencil Drawing Production
- 一个数据读入时出现的BUG
- RAID详解[RAID0/RAID1/RAID10/RAID5]
- mysql create database
- linux驱动编写32位与64位设备注意事项
- 算法总结:【线段树+扫描线】&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828)
- Qt之可重入与线程安全
- Mysql学习总结(3)——MySql语句大全:创建、授权、查询、修改等
- shell命令 grep不以某字符开头、ssh远程执行命令返回结果、ssh远程执行多个命令输入文件
- [算法学习笔记] AVL树----带有平衡条件的二叉搜索树
- HDU 4586
- 使用 CXF 做 webservice 简单例子
- Mysql学习总结(4)——MySql基础知识、存储引擎与常用数据类型