1 void、void * 、id
1.1 void 和 void *
1.1.1 void
- 关键字表示“空类型”的抽象概念
- 但这里的“空类型”不表示“任意类型”,实际上它也不是一种类型,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西
- 作用:
1、对函数返回值进行限定
2、对函数传入参数进行限定- (void)viewDidLoad { }
// 没有参数的 block 属性 @property (nonatomic, copy) void(^clickBlock)(void);
1.1.2 void *
- void *表示“任意类型的指针” 或 表示“该指针与一地址值相关,但是不清楚在此地址上的对象的类型”。
为什么不用void表示任意类型的数据呢?
大家都知道,C/C++是静态类型的语言,定义变量就会分配内存,然而,不同类型的变量所占内存不同,如果定义一个任意类型的变量,如何为其分配内存呢?所以,C、C++中没有任意类型的变量。
但是,所有指针类型的变量,无论是int、char、string、Student等等,他们的内存空间都是相同的,所以可以定义“任意类型的指针”。
- void * 指针只支持几种有限的操作:
1 与另一个指针进行比较
2 向函数传递void * 指针或从函数返回void * 指针
3 给另一个void *指针赋值
不允许使用void * 指针操作它所指向的对象,例如,不允许对void * 指针进行解引用
不允许对void * 指针进行算术操作
1.1.2 REF
C语言void关键字_C语言中文网
C/C++中的函数中的void和void* 理解 - 程序园
1.2 id、NSObject
1.2.1 id 定义 和 官方解析-id
- id是一个指针,用于表示OC 任意类型实例对象的指针,默认告诉编译器该指针指向的对象可以调用任何方法,下面情况编译通过
id aObject = nil;
[aObject appendString:@"xx"];
1.2.2 NSObject
- NSObject是 OC 类的基类对象(官方解析NSObject)
- NSObject 本质是C++的结构体,其表现形式(OC 转 C++代码方法参考NSObject 对象占用内存、isa/superclass指向、类信息存放 - 简书)
在 C++文件中,NSObject表现形式如下
1.2.3 id 和 NSObject 定义对比
NSObject定义:typedef struct objc_object NSObject;
id 定义typedef struct objc_object *id;
其中 objc_object 定义:
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
- 所以,NSObject 是 objc_object类型结构体的别名,而 id 则是 objc_object类型结构体的的指针
- 即
id obj = [[NSObject alloc] init];
等同于NSObject *obj = [[NSObject alloc] init];
1.2.4 id 等同于 NSObject *吗
- 不等同,id 没有指定类型,而NSObject *则指定了类型即NSObject
id 编译通过
NSObject *编译不通过id aObject = nil; [aObject appendString:@"xx"];
NSObject *aObject = nil; [aObject appendString:@"xx"]; // error: No visible @interface for 'NSObject' declares the selector 'appendString:'
- 还需要理解一点就是,NSObject 是 OC 的基类,但是 OC 并非所有类都继承自 NSObject,例如 NSProxy 类。或自定义的其他 OC 类,那么此时就需要引入 id来表示。
-
同上道理,id 一般用于 delegate 的声明,因为一般情况下是不知道 delegate 的实际类型是什么
REF
- https://stackoverflow.com/a/7904028
- id vs NSObject vs id<NSObject> 原文版 翻译版
1.3 id 和 void *
- id is a pointer to any type, but unlike void * it always points to an Objective-C object
- id 的定义
typedef struct objc_object *id;
,也就表明,它是表示一个结构体类型,而不是空 void 类型。在内存分布上即存放该指针的内存
2 nil、Nil、NSNull、NULL
- nil:指向一个对象的空指针(用于表示OC中的
空
实例对象)
NSString *str = nil;
- Nil:指向一个类的空指针(用于表示OC中的
空
类对象)
Class someClass = Nil;
- NSNull:用于表示集合对象(NSArray,NSDictionary,NSSet)中的空值
在集合对象中nil代表结束,故不能用nil代表空值存放于集合中
NSArray *arr = @[@"1", @"2", @"3", [NSNull null]];
- NULL:指向其他类型(基本数据类型,C语言类型)的空指针
// void * 类型的 context 参数,一般使用调用时,如果想不传参给 context,此时正确做法是传入 NULL
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
[self.person1 addObserver:self forKeyPath:@"age" options: NSKeyValueObservingOptionNew context:NULL]