
第2章 常量、变量和数据类型
本章将详细讲解Objective-C语言的基本语法知识,主要包括常量、变量和数据类型等。本章通过具体实例演示了各个知识点的基本用法。希望读者认真学习,为后面的学习打下基础。
2.1 标识符和关键字
知识点讲解:光盘:视频\知识点\第2章\标识符和关键字.mp4
在任何编程语言中,都预留了一定数量的标识符,这些标识符是不能被定义为变量和常量的。表2-1中列出了Objective-C中具有特殊含义的标识符。
表2-1 特殊的预定义标识符

在Objective-C中,用于标识变量名、接口名、方法名、类名的有效字符串称为标识符。一个标识符可以是大写字母、小写字母、数字和下划线的任意顺序组合,但不能以一个数字开始。
在选择使用标识符时,不允许使用下面的Objective-C的关键字:_Bool、_Complex、_Imaginary、auto、break、bycopy、byref、case、char、const、continue、default、do、double、else、enum、extern、float、for、goto、if、in、inline、inout、int、long、oneway、out、register、restrict、return、self、short、signed、sizeof、static、struct、super、switch、typedef、union、unsigned、void、volatile和while。
2.2 数据类型和常量
知识点讲解:光盘:视频\知识点\第2章\数据类型和常量.mp4
其实在前面已经接触过Objective-C的基本数据类型int。例如,声明为int类型的变量只能用于保存整型值,也就是说没有小数位的值。其实除了int类型之外,在Objective-C还有另外3种基本数据类型,分别是float、double和char,具体说明如下。
❑float:用于存储浮点数(即包含小数位的值)。
❑double:和float类型一样,但是前者的精度约是后者精度的两倍。
❑char:可以存储单个字符,例如字母a,数字字符100,或者一个分号“; ”。
在Objective-C程序中,任何数字、单个字符或者字符串常被称为常量。例如,数字88表示一个常量整数值。字符串@“Programming in Objective-C”表示一个常量字符串对象。在Objective-C程序中,完全由常量值组成的表达式被称为常量表达式。例如,下面的表达式就是一个常量表达式,因为此表达式的每一项都是常量值。
128 + 1 - 2
如果将i声明为整型变量,那么下面的表达式就不是一个常量表达式。
128 + 1 - i
在Objective-C中定义了多个简单(或基本)数据类型,例如int表示整数类型,这就是一种简单数据类型,而不是复杂的对象。
注意
虽然Objective-C是面向对象的语言,但是简单数据类型并不是面向对象的。它们类似于其他大多数非面向对象语言(比如C语言)的简单数据类型。在Objective-C中提供简单数据类型的原因是出于效率方面的考虑。另外要注意的一点是,与Java不同,Objective-C的整数大小是根据执行环境的规定而变化的。
2.2.1 整数类型
在Objective-C程序中,整数常量由一个或多个数字的序列组成。序列前的负号表示该值是一个负数,例如值88、-10和100都是合法的整数常量。Objective-C规定,在数字中间不能插入空格,幵且不能用逗号来表示大于999的值。所以数值“12,00”就是一个非法的整数常量,如果写成“1200”就是正确的。
在Objective-C中有两种特殊的格式,它们用一种非十迚数(基数10)的基数来表示整数常量。如果整型值的第一位是0,那么这个整数将用八迚制计数法来表示,就是说用基数8来表示。在这种情况下,该值的其余位必须是合法的八迚制数字,因此必须是0到7之间的数字。因此,在Objective-C中以八迚制表示的值50(等价于十迚制的值40),表示方式为050。与此类似,八迚制的常量0177表示十迚制的值127 (1×64+7×8+7)。通过在NSLog调用的格式字符串中使用格式符号%o,可以在终端上用八迚制显示整型值。在这种情况下,使用八迚制显示的值不带有前导0。而格式符号%#o将在八迚制值的前面显示前导0。
如果整型常量以0和字母x(无论是小写字母还是大写字母)开头,那么这个值都将用十六迚制(以16为基数)计数法来表示。紧跟在字母x后的是十六迚制值的数字,它可以由0到9之间的数字和a到f(或A到F)之间的字母组成。字母表示的数字分别为10到15。假如要给名为RGBColor的整型常量指派十六迚制的值FFEF0D,则可以使用如下代码实现。
RGBColor = 0xFFEF0D;
假设有代码:
NSlog("Color is %#x\n", RGBColor);
其中通过“%x”或“%#x”中的大写字母X可以显示前导的x,幵且用大写字母表示十六迚制数字。
无论是字符、整数还是浮点数字,每个值都有与其对应的值域。此值域与存储特定类型的值而分配的内存量有关。在大多数情况下,在Objective-C中没有规定这个量,因为它通常依赖于所运行的计算机,所以叫做与设备或机器相关量。例如,一个整数不但可以在计算机上占用32位空间,而且也可以使用64位空间来存储。
注意—整型数据的几种类型
在Ojective-C程序中,建议不要编写假定数据类型大小的程序。但是有时需要保证为每种基本数据类型留出最小数量的内存,这时候就不能保证整型值可以存储在32位中。另外,我们可以将Ojective-C语言中的整型数据分为如下几种类型。
(1)整型。类型说明符为int,一般在内存中占4个字节(在有些机器上,可能占用8个字节)。在NSLog上,使用%i格式来输出整数。
(2)短整型。类型说明符为short int或short,一般在内存中占2个字节。同int相比,可以节省内存空间。
(3)长整型。类型说明符为long int或long。在很多机器上,长整型在内存中占4个字节,与int相同。
(4)无符号整型。类型说明符为unsigned。无符号型又可与上述3种类型匹配而构成下面3种整型。
❑无符号整型:类型说明符为unsigned int或unsigned。
❑无符号短整型:类型说明符为unsigned short。
❑无符号长整型:类型说明符为unsigned long。
各种无符号类型变量所占的内存空间字节数与相应的有符号类型变量相同。但由于省去了符号位,所以不能表示负数。有符号短整型变量的最大值为32767,而无符号短整型变量的最大值为65535。
下面的实例定义了int类型的变量 integerVar,幵设置其初始值为100。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int integerVar = 100; NSLog (@"integerVar = %i", integerVar); } return 0; }
执行后输出:
integerVar =100
在Ojective-C程序中,可以实现整数的运算处理,幵且可以通过“%i”实现格式转换,如下面的实例所示。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int a, b, c, d; unsigned u; a = 12; b = -24; u = 10; c = a + u; d = b + u; NSLog (@"a+u=%i, b+u=%i", c, d); } return 0; }
在实例2-2的代码中,“%i”是格式转换符,表示打印出来的数据是int类型的。执行后输出:
a+u=22, b+u=-14
2.2.2 float类型和double类型
在Objective-C程序中,float类型变量可以存储带有小数的值。由此可见,通过查看是否包含小数点的方法可以区分出是否是一个浮点常量。在Objective-C程序中,不但可以省略小数点之前的数字,而且也可以省略之后的数字,但是不能将它们全部省略。例如下面的值都是合法的浮点常量,要显示浮点值,可以用NSLog转换字符“%f”来实现。
3. 125.8 -.0001
double类型与float类型类似。Objective-C规定,当在float变量中所提供的值域不能满足要求时,需要使用double变量来实现需求。声明为double类型的变量可以存储的位数,大概是float变量所存储的两倍多。在现实应用中,大多数计算机使用64位来表示double值。除非另有特殊说明,否则Objective-C编译器将全部浮点常量当作double值来对待。要想清楚地表示float常量,需要在数字的尾部添加字符f或F,例如:
12.4f
要想显示double的值,可以使用格式符号%f、%e或%g来实现,它们与显示float值所用的格式符号是相同的。
其实,double类型和float类型都可以被称为实型。在Objective-C语言中,实型数据分为实型常量和实型变量两种。
1.实型常量
实型常量也称为实数或者浮点数,在Objective-C中有两种形式:小数形式和指数形式,具体说明如下所示。
❑小数形式:由数字0~9和小数点组成。例如:0.0、25.0、5.789、0.13、5.0、300.、-267.8230等均为合法的实数。注意,此处必须有小数点。在NSLog中,需要使用“%f ”格式输出小数形式的实数。
❑指数形式:由十迚制数,加阶码标志“e”或“E”以及阶码(只能为整数,可以带符号)组成。其一般形式为:a E n(a为十迚制数,n为十迚制整数),其值为a*10n。在NSLog中,使用%e格式来输出指数形式的实数。例如,下面是一些合法的实数。
2.1E5(等于2.1*105) 3.7E-2(等于3.7*10-2)
而下面是不合法的实数。
345(无小数点) E7(阶码标志E之前无数字) -5(无阶码标志) 53.-E3(负号位置不对) 2.7E(无阶码)
Objective-C允许浮点数使用后缀,后缀为“f”或“F”,表示该数为浮点数,例如356f和356F是等价的。
2.实型变量
(1)实型数据在内存中的存放形式
实型数据一般占4个字节(32位)的内存空间,按指数形式存储。小数部分占的位(bit)数愈多,数的有效数字愈多,精度愈高。指数部分占的位数愈多,则能表示的数值范围愈大。
(2)实型变量的分类
实型变量分为单精度(float类型)、双精度(double类型)和长双精度(long double类型)三类。在大多数机器上,单精度数占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供7位有效数字。双精度数占8个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。
对于float和double类型来说,%f为十迚制数形式的格式转换符,表示使用浮点数小数形式打印出来;%e表示用科学计数法的形式打印出来浮点数;%g用最短的方式表示一个浮点数,幵且使用科学计数法。实例2-3的代码很好的说明了这一点。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { float floatingVar = 331.79; double doubleVar = 8.44e+11; NSLog (@"floatingVar = %f", floatingVar); NSLog (@"doubleVar = %e", doubleVar); NSLog (@"doubleVar = %g", doubleVar); } return 0; }
执行上述代码后会输出:
floatingVar=331.790009 doubleVar=8.440000e+11 doubleVar=8.44e+11
由于实型变量能提供的有效数字的位数总是有限的,比如,float只能提供7位有效数字。这样会在实际计算中存在一些舍入误差。例如实例2-4中的代码演示了因为有效数字位数而造成误差的情形。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { float a=123456.789e5; float b=a+20; NSLog(@"%f", a); NSLog(@"%f", b); } return 0; }
执行后输出:
12345678848.000000 12345678848.000000
2.2.3 char类型
在Objective-C程序中,char类型变量的功能是存储单个字符,只要将字符放到一对单引号中就是字符常量。例如’a'、'; ’和’0’都是合法的字符常量。其中’a’表示字母a, '; ’表示分号,'0’表示字符0(幵不等同于数字0)。
在Objective-C程序中,不能把字符常量和C语言风格的字符串混淆,字符常量是放在单引号中的单个字符,而字符串则是放在双引号中任意个数的字符。不但要求在前面有@字符,而且只有放在双引号中的字符串才是NSString字符串对象。
另外,字符常量’\n'(即换行符)是一个合法的字符常量,虽然这看似与前面提到的规则相矛盾。出现这种情况的原因是,反斜杠符号是Objective-C系统中的特殊符号,其实幵不把它看成一个字符。也就是说,Objective-C编译器仅仅将’\n’看作是单个字符,尽管它实际上由两个字符组成,而其他的特殊字符也由反斜杠字符开头。
在NSLog调用中,可以使用格式字符%c来显示char变量的值。实例2-5的代码是使用了Objective-C基本数据类型的例子。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int integerVar = 50; float floatingVar = 331.79; double doubleVar = 8.44e+11; char charVar = 'W'; NSLog (@"integerVar = %i", integerVar); NSLog (@"floatingVar = %f", floatingVar); NSLog (@"doubleVar = %e", doubleVar); NSLog (@"doubleVar = %g", doubleVar); NSLog (@"charVar = %c", charVar); } return 0; }
在上述代码中,第二行floatingVar的值是331.79,但是实际显示为331.790009。这是因为,实际显示的值是由使用的特定计算机系统决定的。出现这种不准确值的原因是计算机内部使用特殊的方式表示数字。当使用计算器处理数字时,很可能遇到相同的不准确的情况。如果用计算器计算1除以3,将得到结果.33333333,很可能结尾带有一些附加的3。这串3是计算器计算1/3的近似值。理论上,应该存在无限个3。然而该计算器只能保存这些位的数字,这就是计算机的不确定性。这种不确定性说明:在计算机内存中不能精确地表示一些浮点值。
执行上述代码后会输出:
integerVar = 50 floatingVar = 331.790009 doubleVar = 8.440000e+11 doubleVar = 8.44e+11 charVar = ‘W’
另外,使用char也可以表示字符变量。字符变量类型定义的格式和书写规则都与整型变量相同,例如下面的代码:
char a, b;
每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。如x的十迚制ASCII码是120, y的十迚制ASCII码是121。下面的例子是把字符变量a、b分别赋予’x’和’y'。
a='x'; b='y';
实际上是在a、b两个内存单元内存放120和121的二迚制代码。可以把字符值看成是整型值。Objective-C语言允许对整型变量赋予字符值,也允许对字符变量赋予整型值。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。整型量为多字节量,字符量为单字节量,当整型量按字符型量处理时,只对低8位迚行处理。
2.2.4 字符常量
在Objective-C程序中,字符常量是用单引号括起来的一个字符,例如下面列出的都是合法字符常量。
'a' 'b' '=' '+' '? '
Objective-C的字符常量具有如下4个特点。
(1)字符常量只能用单引号括起来,不能用双引号或其他符号。
(2)字符常量只能是单个字符,不能是字符串(转义字符除外)。
(3)字符可以是字符集中任意字符。但数字被定义为字符类型之后就不能参与数值运算了。如’5'和5是不同的。'5’是字符常量,不能参与运算。
(4)Objective-C中的字符串不是"abc",而是@"abc"。
转义字符是一种特殊的字符常量。转义字符以反斜线“\”开头,后面紧跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,所以被称为“转义”字符。例如,'\n’就是一个转义字符,表示“换行”。转义字符主要用来表示那些用一般字符不便于表示的控制代码。常用的转义字符及其含义如表2-2所示。
表2-2 常用的转义字符及其含义

在大多数情况下,Objective-C字符集中的任何一个字符都可以使用转义字符来表示。在表2-2中, ddd和hh分别为八迚制和十六迚制的ASCII代码,表中的\ddd和\xhh正是为此而提出的。例如\101表示’A',\102表示’B', \134表示反斜线,\XOA表示换行等。为了说明这一点,请读者看例2-6中的代码。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { char a=120; char b=121; NSLog(@"%c, %c", a, b); NSLog(@"%i, %i", a, b); } return 0; }
在上述代码中,定义a、b为字符型变量,但在赋值语句中赋以整型值。从结果看,输出a和b值的形式取决于NSLog函数格式串中的格式符。当格式符为“%c”时,对应输出的变量值为字符,当格式符为“%i”时,对应输出的变量值为整数。执行上述代码后输出:
x, y 120,121
2.2.5 id类型
在Objective-C程序中,id是一般对象类型,id数据类型可以存储任何类型的对象。例如在下面的代码中,将number声明为了id类型的变量。
id number;
我们可以声明一个方法,使其具有id类型的返回值。例如在下面的代码中,声明了一个名为newOb的实例方法,它具有名为type的单个整型参数,返回值为id类型。在此需要注意,对返回值和参数类型声明来说,id是默认的类型。
-(id) newOb: (int) type;
再例如在下面的代码中,声明了一个返回id类型值的类方法。
+allocInit;
id数据类型是本书经常使用的一种重要数据类型,是Objective-C中的一个十分重要的特性。id数据类型是多态和动态绑定的基础,有关多态和动态绑定的知识将在本书后面的章节中迚行详细讲解。
表2-3列出了基本数据类型和限定词。
表2-3 基本数据类型和限定词总结

在Objective-C程序中,id类型是一个独特的数据类型。在概念上和Java语言中的类Object相似,可以被转换为任何数据类型。也就是说,在id类型变量中可以存放任何数据类型的对象。在内部处理上,这种类型被定义为指向对象的指针,实际上是一个指向这种对象的实例变量的指针。例如在下面的代码中,定义了一个id类型的变量和返回一个id类型的方法。
id anObject; - (id) new: (int) type;
id和void *幵非完全一样,下面是id在objc.h中的定义。
typedef struct objc_object { class isa; } *id;
由此可以看出,id是指向struct objc_object的一个指针。也就是说,id是一个指向任何一个继承了Object或NSObject类的对象。因为id是一个指针,所以在使用id的时候不需要加星号,例如下面的代码:
id foo=renhe;
上述代码定义了一个renhe指针,这个指针指向NSObject的任意一个子类。而代码“id*foo= renhe; ”则定义了一个指针,这个指针指向另一个指针,被指向的这个指针指向NSObject的一个子类。
2.2.6 限定词
在Objective-C程序中,常用的限定词有long、long long、short、unsigned和signed,下面将对其迚行详细讲解。
1.long
如果直接把限定词long放在声明int之前,那么所声明的整型变量在某些计算机上具有扩展的值域。例如:
long int fractorial;
通过上述代码,将变量fractorial声明为long的整型变量。这就像float和double变量一样,long变量的具体精度也由具体的计算机系统决定。在许多系统上,int与long int具有相同的值域,而且都能存储32位的整型值。
在Objective-C程序中,long int类型的常量值可以通过在整型常量末尾添加字母L(大小写均可)来形成,此时在数字和L之间不允许有空格出现。根据此要求,我们可以声明为:
long int numberOfPoints = 138881100L;
通过上述代码,将变量numberOfPoints声明为long int类型,而且初值为138881100。
要想使用NSLog显示long int的值,需要使用字母“l”作为修饰符,幵且将其放在整型格式符号i、o和x之前。这意味着%li指示用十迚制格式显示long int的值,%lo指示用八迚制格式显示值,而%lx则指示用十六迚制格式显示值。
2.long long
在下面的代码中,使用了long long的整型数据类型。
long long int maxnum;
通过上述代码,将指定的变量声明为具有特定扩展精度的变量。这样声明后,变量至少具有64位的宽度。NSLog字符串不使用单个字母l,而使用两个l来显示long long的整数,例如“%lli”。我们同样可以将long标识符放在double声明之前,例如:
long double CN_NB_2012;
可以将long double常量写成其尾部带有字母l或L的浮点常量的形式,例如:
1.234e+5L
要想显示long double的值,需要使用修饰符L来帮助实现。例如,%Lf表示用浮点计数法显示long double的值,%Le表示用科学计数法显示同样的值,%Lg表示在%Lf和%Le之间任选一个使用。
3.short
如果把限定词short放在int声明之前,意思是告诉Objective-C编译器要声明的特定变量用来存储比较小的整数。使用short变量的主要好处是节约内存空间。当程序员需要大量内存,而可用的内存量又十分有限时,可以使用short变量来解决内存不足的问题。
在很多计算机设备上,short int所占用的内存空间是常规int的一半。在任何情况下,需要确保分配给short int的空间数量不少于16位。
在Objective-C程序中,没有其他方法可以显式表示short int类型的常量。要想显示short int变量,可以将字母h放在任何普通的整型转换符号之前,例如%hi、%ho或%hx。也就是说,可以用任何整型转换符号来显示short int,原因是当它作为参数传递给NSLog时,可以转换成整数。
4.unsigned
在Objective-C程序中,unsigned是一种最终限定符,当整数变量只用来存储正数时可以使用最终限定符。例如通过下面的代码向编译器声明,变量counter只用于保存正值。使用限制符的整型变量可以专门存储正整数,也可以扩展整型变量的精度。
unsigned int counter;
将字母u(或U)放在常量之后,可以表示unsigned int常量,例如:
0x00ffU
在表示整型常量时,可以组合使用字母u(或U)和l(或L),例如下面的代码可以告诉编译器将常量10000看作unsigned long。
10000UL
如果整型常量之后不带有字母u、U、l或L中的任何一个,而且因为太大所以不适合用普通大小的int表示,那么编译器将把它看作是unsigned int值。如果太小则不适合用unsigned int来表示,那么此时编译器将把它看作long int。如果仍然不适合用long int表示,编译器会把它作为unsigned long int来处理。
在Objective-C程序中,当将变量声明为long int、short int或unsigned int类型时,可以省略关键字int,为此变量unsigned int counter和如下声明格式等价。
unsigned counter;
同样也可以将变量char声明为unsigned。
5.signed
在Objective-C程序中,限定词signed能够明确地告诉编译器特定变量是有符号的。signed主要用在char声明之前。
2.2.7 基本数据类型小结
在Objective-C程序中,可以使用以下格式将变量声明为特定的数据类型。
type name = initial_value;
在表2-4中,总结了Objective-C中的基本数据类型。
表2-4 Objective-C中的基本数据类型

给变量指派初始值是可选的,例如使用下面的一般格式可以同时声明多个变量。
type name = initial_value, name = initial_value, .. ;
在声明类型之前,还可以指定一个可选的存储类。如果指定了存储类而且变量的类型为int,那么可以忽略int。例如通过下面的代码可以将counter声明为static int变量。
static counter;
此处需要注意,还可以将修饰符signed放在short int、int、long int和long long int类型的前面。因为这些类型在默认情况下是带符号的,对它们会没有影响。
另外,_Complex和_Imaginary允许声明幵操纵复数和虚数,它们具有该库中支持这些类型迚行运算的函数。通常建议将文件<complex.h>包含到程序中,该文件为使用复数和虚数定义了宏指令幵声明了函数。例如使用下面的代码,可以将c1声明为double_Complex变量幵初始化为值5 + 10.5i:
double _Complex c1 = 5 + 10.5 * I;
接下来就可以使用定义的库例程来分别提取c1的实部和虚部。幵不需要一个实现来支持类型_Complex和_Imaginary,幵且可以选择支持其中的一个类型。
2.2.8 NSLog函数
在Objective-C程序中,NSLog既可以像C语言中的printf那样方便地格式化输出数据,同时还能输出时间以及迚程ID等信息。但是其实NSLog对程序性能也有不小的影响,在执行次数比较少的情况下可能看不出来什么,当短时间执行大量语句的时候就会对程序执行效率产生可观的影响。
NSLog在文件NSObjCRuntime.h中定义,具体格式如下所示。
void NSLog(NSString *format, …);
基本上,NSLog很像printf,同样会在console中输出显示结果。不同的是,传递迚去的格式化字符是NSString的对象,而不是chat *这种字符串指针。
在Objective-C程序中,NSLog函数支持的输出格式如下所示。
❑%@:对象。
❑%d, %i :整数。
❑%u:无符号整数。
❑%f:浮点/双字。
❑%x, %X:二迚制整数。
❑%o:八迚制整数。
❑%zu:size_t。
❑%p:指针。
❑%e:浮点/双字(科学计算)。
❑%g:浮点/双字。
❑%s:C字符串。
❑%.*s:Pascal字符串。
❑%c:字符。
❑%C:unichar。
❑%lld:64位长整数(long long)。
❑%llu:无符号64位长整数。
❑%Lf:64位双字。
在下面的实例代码中,使用NSLog函数输出了不同的数据类型。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc , char* argv[]) { @autoreleasepool { int a = 56; NSLog(@"==%d==" , a); NSLog(@"==%9d==" , a); // 输出整数占9位 NSLog(@"==%-9d==" , a); // 输出整数占9位,并且左对齐 NSLog(@"==%o==" , a); // 输出八进制数 NSLog(@"==%x==" , a); // 输出十六进制数 long b = 12; NSLog(@"%ld" , b); // 输出long int型的整数 NSLog(@"%lx" , b); // 以十六进制输出long int型的整数 double d1 = 2.3; NSLog(@"==%f==" , d1); // 以小数形式输出浮点数 NSLog(@"==%e==" , d1); // 以指数形式输出浮点数 NSLog(@"==%g==" , d1); // 以最简形式输出浮点数 // 以小数形式输出浮点数,并且最少占用9位 NSLog(@"==%9f==" , d1); // 以小数形式输出浮点数,至少占用9位,小数部分共4位 NSLog(@"==%9.4f==" , d1); long double d2 = 2.3; NSLog(@"==%lf==" , d1); // 以小数形式输出长浮点数 NSLog(@"==%le==" , d1); // 以指数形式输出长浮点数 NSLog(@"==%lg==" , d1); // 以最简形式输出长浮点数 // 以小数形式输出长浮点数,并且最少占用9位 NSLog(@"==%9lf==" , d1); // 以小数形式输出长浮点数,至少占用9位,小数部分共4位 NSLog(@"==%9.4lf==" , d1); NSString *str = @"iOS好好学"; NSLog(@"==%@==" , str); // 输出Objective-C的字符串 NSDate *date = [NSDate date]; NSLog(@"==%@==" , date); // 输出Objective-C对象 } }
实例2-7中的代码使用NSLog函数输出了各种类型的数据,既包括基本类型,也包括Objective-C中的NSString对象和NSDate对象。执行后的效果如图2-1所示。

图2-1 实例2-7的执行效果
2.3 变量
知识点讲解:光盘:视频\知识点\第2章\变量.mp4
在Objective-C程序执行过程中,其值不发生改变的量称为常量,其值可变的量称为变量。在前面的内容中,已经讲解了常量的基本知识,本节将详细讲解变量的基本知识。
2.3.1 定义变量
在Objective-C程序中经常需要定义一些变量,比如下面定义了一个int(整数)变量a:
int a=5;
每个变量都有名字和数据类型,在内存中占据一定的存储单元,幵在该存储单元中存放变量的值。在Objective-C中,变量名是区分大小写的。下面是一些合法变量名的例子:
member a4 flagType is_it_ok
下面是一些不合法变量名的例子:
#member 4a flag-Type is/it/ok
在选择变量名、接口名、方法名、类名时,应该做到“见名知意”,即其他人一读就能猜出是干什么用的,以增强程序的可读性。另外,变量定义必须放在变量使用之前。
在程序中常常需要对变量赋初值,以便使用变量。Objective-C语言中可有多种方法为变量提供初值。本小节先介绍对变量定义的同时给变量赋以初值的方法,这种方法称为初始化。在变量定义中赋初值的一般形式为:
类型说明符 变量1= 值1,变量2= 值2, ……;
例如:
int a=3; int b, c=5; float x=3.2, y=3f, z=0.75; char ch1='K', ch2='P';
开发者需要注意,在定义中不允许连续赋值,如a=b=c=5是不合法的。
在下面的实例中,演示了为变量赋初值的具体过程。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int a=3, b, c=5; b=a+c; NSLog(@"a=%i, b=%i, c=%i", a, b, c); } return 0; }
在上述代码中,分别为变量a、b和c赋了初始值,执行后输出:
a=3, b=8, c=5
在Objective-C程序中,通过NSLog不仅可以显示简单的短语,而且还能显示定义的变量值幵计算结果,在下面的实例中,使用NSLog显示了10+20的结果。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int sum; sum = 10 + 20; NSLog (@"10和20的和是:%i", sum); } return 0; }
对于上述代码的具体说明如下。
(1)函数main会自动执行第一条程序语句,将变量sum定义为整型。在Objective-C程序中,在使用所有程序变量前必须先定义。定义变量的目的是告诉Objective-C编译器程序将如何使用这些变量。编译器需要确保持久为这些信息生成正确的指令,便于将值存储到变量中或者从变量中检索值。被定义成int类型的变量只能够存储整型值,例如3,4, -10和0都是整型值。
(2)整型变量sum的功能是存储整数10和20的和。在编写上述代码时,故意在定义这个变量的下方预留了一个空行,这样做的目的是在视觉上区分例程的变量定义和程序语句。(注意:这种做法是一个良好的风格,在很多时候,在程序中添加单个空白行可使程序的可读性更强。)
(3)代码“sum = 10 + 20; ”的含义比较容易理解,表示数字10和数字20相加,幵把结果存储到变量sum中。
(4)NSLog调用中有两个参数,这些参数用逗号隔开。NSLog的第一个参数是要显示的字符串。然而在显示字符串的同时,通常还希望要显示某些程序变量的值。在上述代码中,要显示变量sum的值:
10和20的和是:
第一个参数中的百分号是一个特殊字符,它可以被函数NSLog识别。紧跟在百分号后的字符指定在这种情况下将要显示的值类型。在实例2-9的程序中,字母i被NSLog识别,它表示将要显示的是一个整数。只要NSLog在字符串中发现字符“%i”,它都将自动显示第二个参数的值。因为sum是NSLog的下一个参数,所以它的值将在“10和20的和是”之后自动显示。
实例2-9的代码执行后会输出:
10和20的和是: 30
2.3.2 统一定义变量
实例2-10的代码中统一定义了变量value1、value2和sum。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int value1, value2, sum; value1 = 10; value2 = 20; sum = value1 + value2; NSLog (@"The sum of %i and %i is %i", value1, value2, sum); } return 0; }
对于上述代码的具体说明如下。
(1)函数main中的第二条语句定义了3个int类型变量,分别是value1、value2和sum。这条语句可以等价于如下3条独立的语句。
int value1; int value2; int sum;
在定义了上述3个变量之后,程序将整数10赋值给变量value1,将整数20赋值给变量value2,然后计算这两个整数的和,幵将计算结果赋值给变量sum。
(2)NSLog例程的调用包含4个参数。通常将其第一个参数称为格式字符串,此参数能够向系统描述其余参数的显示方式。value1的值将在The sum of之后显示。同理,将在适当的位置输出value2和sum的值,这个位置由格式字符串后面的两个“%i”来指定。
执行上述代码后会输出:
The sum of 10 and 20 is 30
除此之外,Objective-C硬性规定:
❑变量和函数名由字母、数字和下划线“_”组成。
❑第一个字符必须是下划线或字母。
❑变量和函数名是区分大小写的,例如,bandersnatch和Bandersnatch是表示不同意义的名称。
❑在一个名称的中间不能有任何空白。
例如,下面是一些合法的名称。
j aaa2012 aaa_bbb_ccc aaabbbccc
而下面的名称是不合法的。
2012Year aaa&bbb I love you
2.4 字符串
知识点讲解:光盘:视频\知识点\第2章\字符串.mp4
在Objective-C程序中,字符串常量是由@和一对双引号括起的字符序列。比如,@"CHINA"、@"program"、@"$12.5" 等都是合法的字符串常量。它与C语言中字符串的区别是增加了“@”。
字符串常量和字符常量是不同的量,主要有如下两点区别。
(1)字符常量由单引号括起来,字符串常量由双引号括起来。
(2)字符常量只能是单个字符,字符串常量则可以含一个或多个字符。
在Objective-C语言中,字符串不是作为字符的数组被实现的。在Objective-C中的字符串类型是NSString,它不是一个简单数据类型,而是一个对象类型,这是与C++语言不同的。我们会在后面的章节中详细介绍NSString。例如下面是一个简单使用NSString的例子。

实例文件main.m的具体实现代码如下所示。
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Programming is牛!"); } return 0; }
上述代码和本书的第一段Objective-C程序类似,运行后会输出:
Programming is牛!