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

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字节对齐。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值