iOS开发之32位与64位,以及结构体对齐访问的问题

xiaoxiao2021-02-28  5

1.首先说32位与64位的问题

之前不清楚iOS是32位还是64位的时候,看见sizeof(int) 打印出来的结果是4的时候,就单纯地以为是32位的系统,即便是看到Mac的“关于本机”里的内存大小清清楚楚地写着是16G(64位OS内存一般为16G,即2的64次方),我也天真地以为大概macOS 和iOS 两者位宽大概不一样吧。因为楼主以前学Linux的,我清清楚楚地记得老师说:int 整型 的“整”体现在它与CPU本身的位宽一样。那iOS是基于Unix,Linux又是高仿的Unix,我就以为一样啊....所以是一直都是这么测的啊,直到,脑抽直接把指针传给sizeof,打印出来是8,

char *p = NULL; printf("------- sizeof(p) = %ld ----\n", sizeof(p));

打印结果:

------- sizeof(p) = 8 ----

8字节,那为什么int只有4字节?凌乱....

然后在网上好一顿搜索,确实也找到了一些资料:(来自iOS32位和64位的坑  这篇文章挺好)

对于iOS设备来说

32位编译器

char :1个字节 char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器) short int : 2个字节 int: 4个字节 unsigned int : 4个字节 float: 4个字节 double: 8个字节 long: 4个字节,最大是2147483648,再大则溢出 long long: 8个字节 unsigned long: 4个字节

64位编译器

char :1个字节 char*(即指针变量): 8个字节 short int : 2个字节 int: 4个字节 unsigned int : 4个字节 float: 4个字节 double: 8个字节 long: 8个字节,最大是18446744073709552000 long long: 8个字节 unsigned long: 8个字节

比较得知,32与64区别主要在long,64位比32位大得多。 (这部分都是粘贴自iOS32位和64位的坑  这篇文章)

那现在已经明白了,目前在用的是64位系统,跟Linux毕竟还是不一样,不纠结这个问题了,继续下一个。

2.其次是结构体对齐访问的问题

前面既然已经说了是64位,可是新疑问又来了

typedef struct my_Header { char msgHead[4]; short tag; int length; }My_Header; My_Header myHeader; memset(&myHeader, 0, sizeof(myHeader)); printf("------- head len = %d ----\n", sizeof(myHeader)); 按照结构体的对齐访问,OS的位宽又是8字节,所以猜测打印出来的结果应该是16字节,... 但是实际打印的是12字节, 这又是怎么肥事?要不是找到了上面的那篇资料,我真的又要以为iOS是32位的了,网上搜了好多,基本也是讲32位下的4字节对齐访问方式。 既然说到结构体的对齐访问,不如一起来复习一下,(以下内容都是基于Linux的32位平台下的,iOS平台下的内容有待考究,不过可以参考)

结构体的对齐访问:

What:

struct header { char a; int b; }; struct header haed; 在这个结构体中,打印输出该结构体的字节,发现它占了8个字节。char a 本应是1字节,但实际在这个结构体中,占4字节,这就是“对齐访问”。

Why:为何要对齐访问

1.硬件限制 2.提高效率: 关于效率这方面,我们要从汇编语言这方面切入理解,比较对齐与不对齐访问: 1)对齐访问: 如上图,此时的b,通过一次ldr指令,即可访问到 2)非对齐访问: 如下图 则读取b的步骤变成了: 1.  读取这3个字节 2. 读取这一个字节 3. 结合

综上,1. 速度降低了2/3,所以效率低。

           2. 对齐访问是牺牲了内存空间,换取了速度。

How:

编译器默认是4字节对齐(32bit),可以通过设置对齐指令来更改对齐方式(1字节对齐、4、8、128字节对齐等) #prama pack(n) // 开头。n = 1, 4, 8... ...... ...... #prama pack() // 结尾

现在再来看看 sizeof(myHeader) 值为 12这事,还是觉得像4字节对齐。 不如再给myHeader加一个类型为long的成员: typedef struct my_Header { char msgHead[4]; short tag; int length; long test; }My_Header; My_Header myHeader;long为8字节,按照上面所讲,如果结构体是4字节对齐: (图误,应该和下一张图是一样的) 应该得出结构体所占大小为20字节; 如果是8字节对齐,则: 结构体所占大小为24字节 既然之前sizeof(myHeader) 值为 12,暂时认为是4字节对齐吧,那么按照刚才的分析,结构体所占大小应该为20字节 我们来实际运行看一看 …… ------- head len = 24 ---- 这下怎么圆回来?前面已经说了那么多 这要怎么理解?此处暂时存疑吧…… 我已经尽我最大努力画图了,看不看得懂全凭缘分了。 不过4字节对齐,8毕竟也是它的倍数,按刚刚的思路,仿佛是不影响…也没有找到什么确切的文章,只能理解成它是默认按4字节对齐的吧。…… ======================= 8月3日,更新  ======================= 其实刚刚最后一张图画完,就已经有点思路了,倒数第二张画的图有误,因为之前说了是在64位的条件下,所以画成4字节的位宽是不对的。 重新更正为: 如果结构体是4字节对齐,情况和下面一张图是一样的。 同理, typedef struct my_Header { char msgHead[4]; short tag; int length; }My_Header;结构体大小为12也可以被理解: 如果真的是8字节对齐访问的话,大小应该为8的倍数,所以可以判断OS并不是按8字节对齐的。 想要验证也很简单,用上面刚刚说的#prama pack(8)测试一下,可以得到结果为16 。

总结:

iOS情况下,是位宽为8字节,结构体对齐方式为按4字节对齐。

转载请注明原文地址: https://www.6miu.com/read-1150136.html

最新回复(0)