今天同样一段代码在xshell上跑和visual c++上跑得到不一样的结果:
sizeof(char *) = 8 //linux
sizeof(char *) = 4 //windows
原因是和系统及编译器有关。
64位系统的寻址空间为2^64,保存一个指针需要64bit即8字节;
32位系统的寻址空间为2^32,保存一个指针需要32bit即4字节;
故以上差别可以用来判断系统是多少位的。
2、不同系统下其他数据类型的差别
在32位系统中,sizeof(long) = 4;sizeof(void *) = 4;
在64位系统中,sizeof(long) = 8;sizeof(void *) = 8;
在两个系统中,其他的数据类型基本一致,如sizeof(int) = 8;
另外在64位系统下long使用%ld,指针使用%p。若用%x打印一个地址,只会显示低4字节的内容。还需注意long与int转换时的截断,以及不要相互赋值。不要使用指针来存放 int 类型的值。例如:
int *ptr;
int i;
ptr = (int *) i;
在开发中要牢记long和指针类型的长度!
更多详情参见 32位与64位下各类型长度对比
3、结构体
struct score
{
int a;
int b;
int c;
};
struct score s; // 3个学生的成绩,结构体的方式
int *p =(int *)&s;
s.a = 12; // 编译器在内部还是转成指针式访问 int *p =(int *)&s; *(p+0) = 12;
s.b = 44; // int *p =(int *)&s; *(p+1) = 44;
s.c = 64; // int *p =(int *)&s; *(p+2) = 64;
4、结构体内存的对齐
参考在64位系统以及64位编译器下字节对齐----阿里巴巴2015实习生笔试题
5、取消内存对其访问__attribute__((packed))
__attribute__关键字主要是用来在函数或数据声明中设置其属性。GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
函数属性:函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。__attribute__机制也很容易同非GNU应用程序做到兼容之功效。
给函数赋给属性的主要目的在于让编译器进行优化。如函数声明中的__attribute__((noreturn)),就是告诉编译器这个函数不会返回给调用者,以便编译器在优化时去掉不必要的函数返回代码。
__attribute__语法格式为:
__attribute__ ((attribute-list)) 其位置约束为:放于声明的尾部“;”之前。
packed是类型属性(Type Attribute)的一个参数,使用packed可以减小对象占用的空间。需要注意的是,attribute属性的效力与你的连接器也有关,如果你的连接器最大只支持16字节对齐,那么你此时定义32字节对齐也是无济于事的。
使用该属性对struct或者union类型进行定义,设定其类型的每一个变量的内存约束。当用在enum类型定义时,暗示了应该使用最小完整的类型(it indicates that the smallest integral type should be used)。
__attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的,我在windows下,用vc的编译器也不是紧凑的,用tc的编译器就是紧凑的。
【例】下面的例子中,my-packed-struct类型的变量数组中的值会紧凑在一起,但内部成员变量中的结构体s不会被“pack”,如果希望内部的成员变量也被packed的话,my-unpacked-struct也需要使用packed进行相应的约束。
struct my_unpacked_struct
{
char c;
int i;
};
struct my_packed_struct
{
char c;
int i;
struct my_unpacked_struct s;
}__attribute__ ((__packed__));
__attribute__ ((aligned(4))); 表示4字节对齐