[Objective-C]简介、数据类型、NSLog、运算符

1. OC历史简介:

    1) 以后OC就作为Objective-C的简称了;

    2) 大致经过:

         i) 最早由Brad J.Cox创造,仅仅是对C语言进行了一定的扩展,因此具有C语言的特性,但很多语法基于SmallTalk,因此是面向对象的;

         ii) NeXT公司获得OC授权,并发展出了OC的语言库和开发环境(该环境基于NEXTSTEP操作系统),该环境即为NEXTSTEP,简称NS;

         iii) NeXT和Sun联合发布针对NEXTSTEP系统的标准规范OPENSTEP,从此该开发环境全称为NEXTSTEP/OPENSTEP,即OPENSTEP标准下的NEXTSTEP环境;

         iv) NeXT被苹果收购,NEXTSTEP/OPENSTEP被苹果整合置自己的操作系统OS X中作为默认的开发环境,并改名为Cocoa(就相当于OS X的API了),并内置了对OC的支持,因此现在在写OC代码时经常会看到以NS打头的函数,这个就代表是原来NEXTSTEP框架中的函数;


2. 第一个Hello World程序:

    1) 程序示例:

// main.m

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    
    @autoreleasepool {
        
        NSLog(@"Hello, World!");
        NSLog(@"fuck");
    }
    
    return 0;
}

    2) 和C语言相通的一些基本特性:

         i) 格式自由:空白符随意加;

         ii) 注释方式://和/* */,其中后者不支持嵌套注释!

         iii) 大小写敏感;

         iv) 花括号框住一段代码块;

         v) 语句以分号;结束(必须加分号!);

         vi) 整个程序的入口函数main函数和C语言的定义也一模一样(包含命令行参数);

    3) #import导入语句和C语言的#include功能一样,都是直接将头文件中的内容复制到原文件中(OC也是实现和声明分开的编程风格),也都是在与处理阶段进行导入;

    4) Foundation/Foundation.h表示Foundation框架中的Foundation.h头文件,这样就可以使用Foudation框架中的NSLog函数了,框架中有很多苹果提供的功能(主要是一些分装了系统调用的函数,和微软的MFC功能类似);

补充:Cocoa框架就是Foundation框架和AppKit框架组成,用于编写OS X应用程序,而开发IOS应用程序的框架是Cocoa Touch框架,由Foundation框架和UIKit框架组成,可见Foundation是一种非常重要的基础框架;

    5) @autoreleasepool { }表示自动释放池,可以自动管理池中动态创建的对象(面向对象中会起到作用,因为OC一开始和C++一样,也是需要程序员自己管理内存的,之后引入了Java那样的垃圾回收机制,但是由于OC一开始并没有垃圾回收的基础模块,因此就开发出了这种方式,即在自动释放池的范围内自动进行内存管理),避免内存泄漏,采用的方式也被沿用到了Swift中,即ARC自动引用计数;

补充:ARC自动引用计数是在OC 2.0中被引入的,因此是一个比较新的概念;

    6) NSLog函数用于向控制台输出一些日志信息,会显示输出时间、产生信息的程序等信息,最重要的是输出参数中的那个字符串并且自动换行;

注意!字符串前面的那个@表示这个字符串不是普通的C语言字符串,而是一个NSString对象,这比使用NSString的构造器来产生对象显得简洁得多;

**提前铺垫:NSLog还支持格式化字符串输出

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {

	@autoreleasepool {
	
		int		a, b, c;

		a = 1;
		b = 2;

		NSLog(@"%i + %i = %i", a, b, a + b);
	}

	return 0;
}
!只不过整型格式不再是C语言的%d而是%i了,即integer的缩写,但不过%d也保留!


3. 编译OC代码:

    1) 命令行上使用命令:clang -o 输出文件名 -fobjc-arc -framework 所依赖的框架 源文件

    2) clang -fobjc表示使用clang的Objective-C编译器进行编译,-arc表示启用OC的ARC引用计数功能,如果不开启将无法使用@autoreleasepool的功能,-framework表示程序中用到的框架,即相当于C语言中连接的库文件;

    3) LLVM简介:是一种集成的编译器框架,全称为Low Level Virtual Machine,它集成了多种语言,各种语言都先会被其编译成LLVM可识别的统一的通用的代码,然后LLVM再将该通用代码编译成本地二进制代码,听起来和JVM很像,但不过LLVM处理的都是编译型语言而不是解释型语言,而苹果的编译器clang底层就是使用LLVM虚拟机;

    4) 完整的编译命令为clang -o a.out -fobjc-arc -framework Foundation main.m


4. 标示符和关键字:

    1) 和C语言一模一样,只不过标示符中还可以用$,并且$可以作为标示符的起始字符;

    2) 标示符的长度在OC中不限;

    3) 关键字和C语言的关键字集一模一样,完全就是C语言的拓展;

    4) OC也有struct、union和指针类型;


5. 空类型和指针简介:

    1) OC也具有指针类型,和C语言的指针类型一样,指针类型也是OC中最为重要的一种数据类型;

    2) 几乎所有的系统类(Cocoa框架)和用户自定义的类的实例都是用指针来访问的;

    3) 空类型:

         i. 即Null Type,其只有唯一值nil;

         ii. 空类型没有相应的关键字名称,因此不可能声明一个空类型量;

         iii. 由于该类型没有名称,因此也不能在空类型和其它类型的数据之间进行类型转换;

         iv. 但是空引用可以转换成任何类型的引用,因此可以将nil看成是指针类型的一个特殊值;


6. 整型:

    1) 和C一样,还是short(short int)、int、long(long int)、long long;

    2) 各种类型应该占几位没有强制规定,只是规定了后者必须大于等于前者,因此要看具体不同的平台;

    3) 以下给出在苹果的机器上各整型的占位情况:

         i. short、int和long long始终占2字节、4字节和8字节;

         ii. 在Mac上long占8字节,在iOS上long占4字节;

    4) 可以在上述所有整型之前加上unsigned关键字表示无符号的整型;

    5) 整型的十六进制和八进制和C语言的表示一模一样,八进制0打头,十六进制0x打头(x以及a~f不区分大小写);


7. 关于NSLog的格式字符串:

    1) NSLog总体用法和C的printf一模一样,但不过它还重载了面向对象的功能,只要类类型实现了到字符串的自动转换就可以实现对对象的输出;

    2) 占位符%X:

十进制有符号整型:d、i

无符号数:u(十进制)、o(八进制,无前缀0)、x(十六进制,无前缀0x)

浮点数:f(6位小数)、e(指数形式,6位小数)、g(自动选用f或e中的一种,不输出无意义的末尾0)

地址:p(十六进制表示的地址)

@:对象

    3) 占位前缀:

一个正整数:整个数的宽度

.自然数:对于浮点数则表示小数位数,对于字符串表示截取的字符个数

-:数值左对齐

l(字母):以上所有的占位符都表示短整型和短浮点型(short、int等小于等于4字节的都是短整型,float是短浮点型),加在d、i、u、o、x、f、e、g之前表示输出长类型数值;


8. 字符型字符串:

    1) 字符型即char型,它和C语言最大的不同是char在OC中是一个1字节的无符号整型,不能表示负数,这点和C语言不一样,C语言的char是有符号的,而unsigned char才是无符号的;

    2) 因此char是一种无符号短整型在OC中;

    3) 字符常量和转义字符定义和C语言一模一样(常量用''括起来,转义则为'\X'的形式);

!!由于char是严格的单字节,所以不能表示中文字符!!

    4) 普通的C串和NSString字符串:

         i. 普通的C串定义和C语言字符串一模一样,都是直接用""引起来;

!但是OC没有宽字符,所以C串中最好只包含单字节字符,而不要包含中文等宽字符,否则会引发不必要的错误;

         ii. NSString字符串支持Unicode等宽字符,因此可以包含中文等宽字符;

         iii. 定义NSString常量:@"..."即可,该种定义将会返回一个NSString的指针,因此完整的定义应该例如NSString* str = @"你好!Hello!123!";


9. 浮点型:

    1) 有float、double、long double三种,分别占4字节、8字节、16字节;

    2) 常数表示形式和C语言一样,只不过没有后缀区别了,无需f后缀来区分短浮点数和长浮点数,编译器会根据大小自动设置其类型;

    3) 科学技术法也只能用于浮点数,用科学技术法表示的整数仍然是浮点类型的;

    4) OC的浮点常量还提供了三个扩充,就是正无穷、负无穷和非数:

         i. 正无穷:inf,整数除以0.0,所有正无穷都相等

         ii. 负无穷:-inf,负数除以0.0,所有负无穷都相等

         iii. 非数:nan,0.0除以0.0,非数不和任何数相等,甚至不和自己相等(正无穷和负无穷在内存中用同一的符号标识,而nan在内存中可能直接保持原样,因此是一个随机数);

!!注意:

       a. 要得到以上三个数必须使表达式结果为浮点数,即除数和被除数至少有一个为浮点数,并且输出格式必须是浮点格式(的任意一种都行);

       b. 整型数除以整型的0等都会抛出运行时异常,因此这三个常量只针对浮点数;

       c. 不要试图用%d等整型格式输出这三个值,会得到随意结果而产生严重的错误;

!!可以用nan == nan来测试nan是否和nan相等,结果是false;


10. 枚举类型:

    1) 和C语言的枚举类型一样;

    2) 定义枚举类型和枚举变量:

enum season { spring, summer, fall, winter };
enum season s = winter; // 声明时必须加上关键字enum来表示season是一种枚举类型,否则会编译报错!!

// 定义匿名枚举类型,需要定义枚举类型的同时也定义变量
enum { male, female } tom, peter;
tom = male;
peter = male;
    3) 在OC中枚举类型的值就是一个unsigned int,所以可以肆无忌惮地当unsigned int来使用,赋值、参与四则运算、比较大小等等;

    4) 枚举常量的值:

         i. 规则和C语言一模一样,如果不自定义值则从左到右依次为0, 1, 2...

         ii. 自定义值的话,比如enum season { spring = 4, haha = 2, summer, fall, winter = 20 }; 则summer = 3,fall = 4,也就是说没有显式定义值的量跟随最近的一个显式值加1递增;

         iii. 但是不管哪种语言,都不建议这样乱用枚举变量,毕竟其本身有更好的可读性;


11. BOOL类型:

    1) 即逻辑值,只有两种常量值,即YES和NO;

    2) 但是在OC底层BOOL就是signed char,即有符号单字节整型:

typedef signed char BOOL;
#if !defined(YES)
    #define YES (BOOL)1
#endif
#if !defined(NO)
    #define NO (BOOL)0
#endif
!也就是说YES和NO在底层就是单字节有符号整型1和0;

!可以将BOOL肆无忌惮得当成signed char来使用,赋值、比较大小、参与运算等等;

    3) 为什么要把BOOL定义成有符号的,因为继承C语言的非0就代表真,0代表假的理念,可以让编程更灵活,因此有时可以直接把一个算术表达式的值作为逻辑判断结果,而该结果的值可能是负的;

    4) 当给一个BOOL类型变量赋一个超过BOOL范围的值时一定要注意,如果该值的低8位刚好是0,那么该BOOL变量的值就成了NO了,就可能跟你“非0就是YES”的初衷相违背而导致严重的错误!!


!!OC中逻辑表达式的类型:可以sizeof(5 > 3)一下,可以看到逻辑表达式占4个字节,其实就是一个int(可以是负),因此在逻辑判断的地方(比如if、while等)可以肆无忌惮得跟C语言一样风骚走位,还可以产生各种副作用,完全就和C语言一样一样滴!!


12. 类型转换和自动提升:

    1) 其自动类型转换和强制类型转换规则和C语言一模一样,强制类型转换也是使用(type)的形式;

    2) 窄化转换的溢出规律也和C语言一样;

    3) 在表达式中类型自动提升的规则也和C语言一模一样,只不过多了一个long double,即short(char) -> int -> long -> long long -> float -> double -> long double;


13. 运算符:

    1) 和C语言一模一样,就是有几点需要提醒;

    2) %的求余运算必须是整型之间的,并且底层会先进行除法运算,因此右边的操作数不能为0;

    3) OC和C一样,也只提供了+、-、*、/、%这五种基本的运算符,如果想使用更复杂的运算方法则直接使用ANSI C的math.h库,该库直接包含在Foundation/Foundation.h中了,因此不需要再显示包含该库;

    4) 其余++、--、位运算符、赋值运算符、复合运算符等都和C语言一模一样,但还是有几点需要提醒:

        i. 赋值表达式是有值的;

        ii. 右移运算符>>左边用原来的符号位补齐;

        iii. 位运算符只适用于整型,如果用于浮点型会直接编译报错;

    5) OC在&&、||、!的基础上还多了一个^逻辑运算符,只有当两边是不同的结果(必须一真一假)才会返回YES,因此^的优先级小于算术运算符,例如:5 > 3 ^ 3 < 5,将返回YES,并且OC的逻辑运算符也具有短路性,如果要利用逻辑运算符产生副作用的话一定要注意不要受到短路性的影响;


14. 逗号运算符和逗号表达式:

    1) 完全和C语言一样,但是需要强调一下;

    2) 整个逗号表达式的返回值是最右边的那个;

    3) 赋值运算符(包括各类复合赋值运算符)的优先级都比逗号运算符要高,因此如果要把一个逗号表达式的值赋给一个变量则需要将整个逗号表达式用括号括起来;


15. 三目运算符:

    1) 即? : :运算符,完全和C语言一样,但还是需要强调一下;

    2) 第一个参数可以用括号也可以不用;

    3) 支持各种嵌套,用法灵活,只要是有返回值的函数都可以作为三目运算符的参数,例如:5 > 3 ? NSLog(@"5 > 3") : NSLog(@"5 < 3");


16. 运算符的优先级:

    1) 和C语言一样,这里不一一说明;

    2) 但还是那句建议的话,不要依赖这种优先级来构造表达式,一旦有需要就积极使用括号,避免因为优先级导致的错误!!

展开阅读全文

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