iOS白话串2-void、void * 、id、NSObject 和 nil、Nil、NSNull、NULL

1 void、void * 、id

1.1 void 和 void *

1.1.1 void

  • 关键字表示“空类型”的抽象概念
  • 但这里的“空类型”不表示“任意类型”,实际上它也不是一种类型,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西
  • 作用:
    1、对函数返回值进行限定
    - (void)viewDidLoad {
    }
    
    2、对函数传入参数进行限定
    // 没有参数的 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

iOS白话串2-void、void * 、id、NSObject 和 nil、Nil、NSNull、NULL_第1张图片
id define
  • id是一个指针,用于表示OC 任意类型实例对象的指针,默认告诉编译器该指针指向的对象可以调用任何方法,下面情况编译通过
id aObject = nil;
[aObject appendString:@"xx"];

1.2.2 NSObject

  • NSObject是 OC 类的基类对象(官方解析NSObject)
  • NSObject 本质是C++的结构体,其表现形式(OC 转 C++代码方法参考NSObject 对象占用内存、isa/superclass指向、类信息存放 - )
    在 C++文件中,NSObject表现形式如下
    iOS白话串2-void、void * 、id、NSObject 和 nil、Nil、NSNull、NULL_第2张图片
    NSObject define

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 编译通过
    id aObject = nil;
    [aObject appendString:@"xx"];
    
    NSObject *编译不通过
    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 原文版 翻译版

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 类型。在内存分布上即存放该指针的内存
    iOS白话串2-void、void * 、id、NSObject 和 nil、Nil、NSNull、NULL_第3张图片

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]

你可能感兴趣的:(iOS白话串2-void、void * 、id、NSObject 和 nil、Nil、NSNull、NULL)