2015-03-06 14:08:31 oqqQuZi1234567 阅读数 981

      在苹果推出iPhone5S时,64位的应用就走到了眼前。当时就看见苹果官方资料宣布iOS7.x的SDK支持了64位的应用,而且内置的应用都已经是64位。

      我记得自己刚刚接触电脑时还有16位的系统,指针的寻址范围还是16位的。当年用TurboC时,还要根据应用的大小选择是tiny模式还是其他。后来很长一段时间使用32位的模型编程,4G是牢牢记住的一个边界条件。而现在,64位走到了眼前。

      就如同16位转向32位一样,硬件肯定是最先推出的,SDK也会跟进,然后各种第三方的应用才会逐步跟进,这个过程一般都需要持续一段时间。这次苹果在推出之后,很长一阵子也处于32位和64位并行的过渡期,但是,随着10月份苹果宣布,2015年2月1日起,上传AppStore的应用都需要支持ARM64了,具体消息请猛戳这里

      于是开始看了一下32位应用如何转成64位应用

1. 基础知识

      Xcode 5.0.1开始支持编译32-bit和64-bit的Binary

      同时支持32-bit和64-bit,我们需要选择的minimum deployment target为 iOS 5.1.1

      64-bit的Binary必须运行在支持64-bit的CPU上,并且最小的OS版本要求是 7.0.3

 

2. 让应用兼容64位的基本步骤

      安装Xcode5.0.1或者以后——其实现在能提交AppStore的Xcode版本最少也要5.1.1

      在Xcode中打开工程,编译,修正错误以及警告,尤其是针对32位和64

      在Project Setting里面,把最小应用使用的SDK改到5.1.1或者更高的版本

      把Architectures参数设置成“Standard Architectures (including 64-bit).”

      这样你的应用就支持了64位的CPU,再次修复编译器的错误和警告,请注意,有些问题编译器是没有警告的

      在64位的真机上测试你的应用

      使用Instruments查看内存使用的状况


3. 从32位到64位的变化

3.1 数据类型的变化

      这里主要是语言内置类型所占的字节数以及字节对齐的不同。在32位的年代,使用的是IPL32的规范,到了64位之后,改成了LP64规范。

      

      除了这些以外,还有浮点类型

            

      数据类型里面,NSInteger在32位时等同于int,在64位时等同于long,而这个数据结构使用很广,很多不规范的时候会直接和int替换使用,在32位是毫无问题,但在64位时,这就是隐患了。CGFloat也有同样的问题,所以代码的检查修改必须仔细。

      至于对齐,如果使用了偏移量来访问struct的项,那么需要认真仔细的检查,其余的还算好,当然如果你用了malloc,那么也请检查一下分配的内存大小,建议是多使用sizeof来帮助计算。

      还有,针对存储的文件,比如存储在iCloud上的文件,你无法确定是一个32位应用还是64位的应用会去访问,那么请一定把数据内容的解释写成一模一样。


3.2 方法调用上的变化

      64位应用要求所有函数都有原型,这本身就是一个好的编码习惯

      函数的造型必须和原型完全一致,尤其要避免参数个数未定的函数指针造型(printf一类)

      在64位系统在运行时调用函数和32位系统是不同的。主要的区别在于传递具有可变参数个数的函数的参数时,我们来看下面的代码:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int fixedFunction(int a, int b);  
  2. int variadicFunction(int a, ...);  
  3.    
  4. int main  
  5. {  
  6.     int value2 = fixedFunction(5,5);  
  7.     int value1 = variadicFunction(5,5);  
  8. }  
      第一个函数是固定传入2个参数,第二个函数是参数个数不定的,在使用中,也传入了2个参数。在32位系统下,这两个函数的参数传递是非常类似的,而在64位系统下,这两者就是截然不同了。


3.3 汇编的不同

      因为是不同的指令集,汇编当然会不同。不过我们一般的应用不会用到汇编,所以这一项比较少遇到。


4. 第三方库

      最后,我们项目中使用的第三方库肯定需要支持64位系统,否则还是白搭。所以大家在升级时需要检查自己使用的第三方的库,看是否已经有64位的版本出现了。


      苹果目前的系统中(iOS7/iOS8),32位的framework和64位的framework是共存的,所以如果所有的应用都是64位的话,系统就自动不加载32位的framework,这样可以少占用资源,另外对运行的速度是有好处的,也就是说,你会感觉手机运行的快了一点。

      应用在兼容64位系统后,内存的占用肯定会变多一点,不过性能也有相应的提升。

参考:点击打开链接


2016-07-26 22:43:19 wu__di 阅读数 6818

  众所周知,苹果是从iPhone 5s开始对全线移动产品使用64位架构,那么如果App需要兼容32位和64位的机型,就需要注意它们之间的区别。

  下面我们首先看看基本数据类型的区别:

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个字节

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个字节

long long:  8个字节

   从上面的比较我们可以看的出来,对于32位的机器来说,long是四个字节,而对于64位机器的long是8字节,如果在项目开发过程中忽略了这个点,很容易出现问题。下面举例分析:

   在我们的项目中,有这样的需求,服务器端返回一个时间戳,单位为毫秒,客户端需要解析该字段并转化为NSDate,存储到数据库中。对64位的机器我们只需要定义一个字段,比如startTime,类型为long,解析字段可以使用objectForKey的longValue获取到时间戳,然后转换为时间类型,没有任何问题。但是在32位,我们发现转换后的时间类型是错误的,类型1970...。究其原因,就是因为32位机器上毫秒级的时间戳longValue后越界,导致后续转换都异常。解决这类问题的方法是在涉及到时间戳为毫秒的情况下,定义相应字段是long long类型,通过longLongValue获取到值,就不存在溢出的情况。

   如果这偏文章能给你带来启发请关注我其他的文章,或者搜索微信号:785798889关注我,谢谢~




2014-06-30 11:12:33 h289962920 阅读数 234

苹果于2013年9月推出了iPhone 5S新手机,采用的全新A7处理器其最大特色就是支持64位运算。其64位A7处理器的使用意味着iPhone性能会大有提高,性能和速度更加出色;而要到达到这样的性能,开发者就要开发64位的应用了。

一、讨论宏观问题

  1. 1

    Xcode 5编译的iOS 7程序包含了32位和64位两套二进制代码,在32位的iOS系统上会调用32位的二进制代码,在64位系统上会调用64位的二进制代码,以此来解决向后兼容的问题。同时,考虑到很多32位的程序可能在没有重新编译的情况下部署到64位系统上,64位的iOS系统中带有两套FrameWork,一套是32位的,一套是64位的。当64位的iOS系统运行原来的32位程序时,系统会调用32位的FrameWork作为底层支撑,当系统运行64位程序时,系统会调用64位的FrameWork作为底层支撑。也就是说,当一个iPhone 5S上同时运行32位程序和64位程序时,系统同时将32位和64位两套FrameWork载入了内存中,所以消耗的内存也比较多。如果一台64位的iOS设备上运行的所有程序都是为64位系统编译过的,iOS系统将只载入64位的FrameWork,这将节省好多内存。所以,如果大家都可以快速将程序传换成64位的,iOS将跑得更快。

    END

二、讨论细节问题

  1. 1

    32位的iOS系统和64位的iOS系统主要的差别有两个,一个是数据类型的差别,一个是过程调用方法的差别。在数据类型上,主要的变化是指针类型(Pointer)和长整数类型(long)的长度变化和内存对齐方式的变化,同时也导致了更高级别数据类型的变化,如NSInteger的长度也有变化。在过程调用方法上,因为ARM V8 和ARM V7具有不同数量的寄存器,具有不同的过程调用约定,所以32位系统和64位系统在汇编层级是不同的。

    END

总结:

  • 开发人员根据以下要点来检查原来的32位代码就可以将应用移植到64位系统上了:1. 不要将长整型数据(long)赋予整型(int)这种代码在32位系统上没有问题,因为在32位系统中long和int的长度是一样的,不过在64位系统中就有可能出问题,因为64位系统中long比int长,将long值赋予int将导致数据丢失。2. 不要将指针类型(Pointer)赋予整型(int)为 了方便地址计算,有时程序员会将指针类型赋予整型,这种代码在32位系统上没有问题,因为在32位系统中Pointer和int的长度是一样的,不过在 64位系统中就会有问题,因为64位系统中Pointer比int长,将Pointer值赋予int将导致地址数据丢失,最终导致严重问题。3. 留意那些和数位相关的数值计算比如掩码技术,如果使用一个long类型的掩码,转到64位系统后高位都是0,计算出来的结果可能不符合预期。还有无符号整数和有符号整数的混用等。4. 留意对齐方式带来的变化如果在32位系统上定义一个结构包含两个long类型,第二个long数值的偏移地址是4,可以通过结构地址+4的方式获取,但是在64位系统上就不行了,因为在64位系统中第二个long数值的偏移地址是8。5. 充分考虑在32位应用和64位应用之间的数据交换因 为用户会通过网络交换数据,同时用户保存的数据也可能通过备份等方式在32位系统和64位系统之间切换,所以应用在保存和发送流数据的时候一定要考虑充 分。比如数据在32位系统中保存,在64位系统中能否正常打开,或者反过来,在64位系统中保存,在32位系统中打开是否正常。6. 重写所有汇编代码这点无需说明,如果你在代码中嵌入了汇编代码,你需要参考64位系统的指令集重写汇编代码。7. 不要将可变参数的过程强制转换为定参过程,也不要将定参过程强制转换为可变参数的过程这时因为32位系统和64位系统对于这两种过程调用方式的处理方法不同。

    END

将以前的应用编译成64位程序

  1. 1

    1. 使用Xcode 5 打开原有项目。

    2. 将支持的设备改成“iOS 7”。

    3. 在“Build Setting”中将“Architectures”改成“Standard Architectures (including 64-bit)”。

    4. 运行测试程序,解决编译过程出现的问题。

2015-10-08 17:13:07 lilinoscar 阅读数 142434

ios二维码扫描,基本上大家都是在用ZBar第三方的库,github上的是32位,如果是在64位的xcode运行,会报错,需要libzbar.a支持64位,网上很少有64位下载的文件,这里提供一个64位下载



下载地址:http://download.csdn.net/detail/lilinoscar/9163683


2017-08-02 23:47:45 a997013919 阅读数 1312

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



没有更多推荐了,返回首页