![iOS开发:从零基础到精通](https://wfqqreader-1252317822.image.myqcloud.com/cover/796/26793796/b_26793796.jpg)
第2章 数据类型与表达式
2.1 数据类型与常量
Objective-C是在C语言基础上拓展出的新语言,所以它是完全兼容C语言代码的,C语言中的基本数据类型如int、float、double和char在Objective-C中是完全可以正常使用的。除此之外,Objective-C还拓展了一些新的数据类型如BOOL、id、instancetype等。
2.1.1 基本数据类型
1.int类型
整数常量由一个或多个数字的序列组成,序列前的负号表示该值是一个负值,数字中间不允许插入空格或逗号。例如:123、–56、2都是合法的整数常量,而“23,000”就是一个非法的整数常量。
一个int类型值的取值范围在不同的设备中是不相同的。在32位的操作系统中,一个int占用4字节;在64位的操作系统当中,一个int占用8字节,所以在64位的操作系统中,int的取值范围是大于32位操作系统的。
在开发过程中,格式化输出一个int型的整数时,可以使用%d或%i。
示例:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T33_4263.jpg?sign=1739262229-ESnjsfUzIz7OsQGSp6zi0YphEMaejlIL-0-a467bdf4175d3d6f4a5a4f9a76c58f62)
运行结果如图2-1所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P33_4265.jpg?sign=1739262229-SmiL17OQXsGn8ySIuTYVPNpG14giKaBw-0-a7305d0c404ce3be42a40b82ae1ccd36)
图2-1 运行结果
2.float类型
float类型可以存储包含小数位的数值。要区分浮点常量,可以看是否包含小数点。例如:2. 、3.67 、.23都是合法的浮点常量。 float类型占用4字节,32位。格式化输出时可以使用%f或者%g。另外,%.2f表示保留2位小数,其他以此类推。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T34_4377.jpg?sign=1739262229-Xzhk99GwaLHA83S8dkYhxOTp4E3wWH7J-0-e270406d8b48ab99386d60e120c55190)
运行结果如图2-2所示。默认情况下,使用%f打印float型的常量,取小数点后6位。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P34_4379.jpg?sign=1739262229-OuMh1CwDC6IXyYbn0feYroANomVSU9RQ-0-d31e87c7723b8e451c75280b820010d4)
图2-2 运行结果
double类型和float类型十分相似,区别就在于它们的取值范围,因为double类型在内存里占用8字节,64位,所以取值范围要比float大很多,但使用方法都是一样的。
3.char类型
char类型的变量可以存储单个字符,将字符放入一对单引号中就可以得到一个字符常量。例如:'a'、'!'、'3'都是合法的字符常量,但字符'3'并不等于整数3,不能混淆。char类型占1字节。格式化输出使用%c。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T34_4383.jpg?sign=1739262229-UD1wB6yHr2fZ4Z5N31VF9ex7pAEiAN4c-0-ee927fc21d192c96c4ab654906c11fe5)
运行结果如图2-3所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P34_4385.jpg?sign=1739262229-ukOtdHlxWfOQIi8lOIHkK0Y33TrzPju5-0-e0b6a310bf3b07fa617233efcb4ad806)
图2-3 运行结果
4.BOOL类型
BOOL类型其实是由一种称为预处理程序的机制添加的。Objective-C中的BOOL实际上是一种对带符号的字符类型(signed char)的类型定义(typedef),它使用8位的存储空间。通过#define指令把YES定义为1,NO定义为0。Objective-C并不会将BOOL作为仅能保存YES或NO值的真正布尔类型来处理。编译器仍将BOOL认作8位二进制数,YES和NO值只是在习惯上的一种理解。例如,给一个BOOL类型的变量赋值为23是可以编译成功的,编译器在处理过程中会将该变量认定为真,因为BOOL类型逻辑上来说是非零即为真。
BOOL类型的本质:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T35_4475.jpg?sign=1739262229-owKuGqOkLoyvv9GNhcOsB0TJukJ2exaF-0-a81541d4ea16288af609279a75842bd3)
BOOL类型变量取值:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T35_4477.jpg?sign=1739262229-ujs79ZlSWm76KhxmFdCaOxxTGbHwo3EE-0-3e51dbb76fedfcddcafc43e2e39c402c)
例如:定义两个BOOL类型的变量,并分别赋值以及打印。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T35_4479.jpg?sign=1739262229-NmZkJQldsT8KHIAZ0TvL41LYV2EW2WoY-0-980312213f82b0a4b2f3255505939365)
运行结果如图2-4所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P35_4481.jpg?sign=1739262229-pDd0vATjAryytDQ8yS8nhxJpaikbDfMf-0-512845659a50ec7061b16b0fce95db66)
图2-4 运行结果
2.1.2 限定词
Objective-C中,在变量的声明过程中,还可以加上一些限定词。常见的一些限定词主要有:long、long long、short、unsigned、signed。
1.long
把限定词long放在int前面,所声明的整形变量在某些计算机上具有扩展的值域。
示例:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T35_4486.jpg?sign=1739262229-Eq4xpr7U8E8DfxOBQKyWUgp7TOglwOvu-0-6db0abe8a957c16816d2588d1586d771)
这条语句表示将number声明为long的整形变量,long变量的具体范围是由系统而定。在许多系统中,int与long int具有相同的值域。 long在限定整型的时候,实际相当于双精度的short。
double前也可以加long,这样可以表示更大的浮点数,但是float前不可以使用long。
格式化输出时,整数需要使用%li或%ld,long double需要使用%lf。
2.long long
long long:双长整型相当于双精度long。
示例:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T36_4557.jpg?sign=1739262229-kLZgjS1GjvVCWo6wnmv9feYyGx28Mfdc-0-2b5fe1a7aed305be0a980e6cc3500306)
变量number具有特定扩展精度的双长整型变量,该扩展精度保证变量至少8字节,具有64位的宽度。格式化输出number时要使用%lld或%lli。
3.short
把限定词short放在int声明之前时,它告诉Objective-C编译器要声明的特定变量用来存储相当小的整数。之所以使用short修饰变量,主要原因是出于对节约内存空间的考虑,当程序员需要大量内存而可用的内存量却十分有限时,比如iPhone开发的时候,就可用short变量来解决这个问题。short int占用的内存空间是常规int变量所占空间的一半。在任何情况下,确保分配给short int的空间数量不少于2个字节,16位。
4.unsigned
顾名思义,就是无符号,可放在int变量之前,当整数变量只用来存储正数的情况下使用该限定符。
示例:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T36_4559.jpg?sign=1739262229-pNi2wDA4cxD2aLfNPtdoXfhz2LQaxzNa-0-aa269f93ae2240a16518a3b70cb0516a)
使用unsigned修饰整型变量,意味着向编译器声明:变量number只用来保存正值。通过限制整型变量的使用,使它专门存储正整数,可以扩展整型变量的精度。一般unsigned int可简写为uint。
5.signed
signed限定词可明确地告诉编译器该整型变量是有符号的。默认情况下long、short、long long修饰的整数都是有符号的,该整数的最高位用来存储符号。而char类型有些区别,signed char:[–2^7, 2^7]即[–128,128]; unsigned char:[0, 2^8]即[0, 256]。
通过下方的示例代码,可以了解到在Objective-C中限定词的使用情况。一般来讲,在实际的开发过程中,限定词的使用并不是十分普遍和广泛,建议初学者了解即可。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T36_4561.jpg?sign=1739262229-fTEA9GgGU8UMjypn5f4FVsS06YMcrsJW-0-da2b7114c35da38ccd6a7d5eef37d85b)
运行结果如图2-5所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P37_84118.jpg?sign=1739262229-liVvls8tLQ3dUUvhHGEU74MTuW9ldGjZ-0-99741af1a10afd2f0a97108be306f6c5)
图2-5 运行结果
2.1.3 id与instancetype
1.id类型
id数据类型可存储任何类型的对象。从某种意义上说,它是通用对象类型,这和C语言中的void *很相似。如果要用基本类型代替,需要对基本数据类型进行封装。 id是一个指向任意一个继承了NSObject类的对象。需要注意的是,id是一个指针,所以在使用id的时候不需要加星号。例如:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T37_4666.jpg?sign=1739262229-kE0zqUzi0kaB5rKYpjfhfSdC4mC09Ooj-0-46a705e87ba3415d78a8026933e2f526)
id类型是Objective-C中经常使用的一种重要数据类型,它是Objective-C动态绑定的基础。
下方的代码中,在一个数组中存储了若干个对象,有NSNumber和NSString型的,当用户无法准确获取对象的类型时,可以使用id这种通用的对象类型。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T37_4668.jpg?sign=1739262229-g5WfxjBbBv1XhzZnAcb8JRh4pEABQJuI-0-15644be2330d51eff15ad466732fad43)
运行结果如图2-6所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P37_4670.jpg?sign=1739262229-pPnEhOmrw2GiC84S3Wwn44hkBM4FfyEi-0-0320a86c4bb72867aa957a5e67d43b9e)
图2-6 运行结果
2.instancetype类型
在类方法中,例如,以alloc、new开头的方法,以及实例方法中autorelease、init、retain等方法的返回值类型就是instancetype类型,这些就称为关联返回类型的方法。这些方法的返回值是一个以方法所在的类为类型的对象。例如,在NSObject类的alloc和init方法,调用后会返回一个NSObject类型的对象。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T38_4719.jpg?sign=1739262229-17TIOrPzZsp1vQDmBzBBdWbHUETHvAZy-0-b087d5a55da1a20f4dcefc21da8cd083)
使用instancetype作为方法返回值的好处是可以确定对象类型,以便帮助编译器更好地定位代码问题。
3.id和instancetype的异同
id和instancetype的相同点在于都可以作为方法的返回值类型。而两者的不同点体现在:
- id可以作为方法或函数的参数的类型,也可以单独用这种类型定义变量,但是instancetype不行。
- 如果方法的返回值类型是instancetype,那么它返回的一定是这个类型的对象;如果方法的返回值类型是id,那么它返回的是未知类型的对象。