zoukankan      html  css  js  c++  java
  • nil/Nil/NULL/NSNull

    一个简单的小例子:
        NSObject *obj = nil;
        NSLog(@"%@",obj); =>null
        NSObject *obj2 = [obj mutableCopy];
        NSLog(@"%@",obj2); =>null
        NSMutableArray *array = [[NSMutableArray alloc] init];
        [array addObject:obj];  =>crash
        NSLog(@"%@",array);
    

    1、简单总结 

         nil:表示   对象的指针指向的那块内存不存在  是一个空对象 指针的值为空(null);

         Nil:表示  类指针指向的那块内存不存在;

         null :表示   空指针(的值)如:int *ponit = NULL;

        nsnull:表示 对象指针指向的内存中的那个值是空;
     

    2、分析   

    2.1、Objective-C 中给 nil 发送消息程序不会崩溃

     id objc_msgSend(id self, SELop, ...)
      // On entry: a1 is the message receiver,
       // a2 is the selector
    

    self 就是方法的调用者 receiver 例子中self = nil;

    原因需要从源代码中寻找,

    下面是 objc_msgSend 的 arm 版汇编代码片段:

    在 arm 的函数调用过程中,

    一般用 r0-r4 传递参数,

    用 r0 传递返回值。

    对应 objc_msgSend,第一个参数为 self,返回值也是 self,都放在 r0(a1)中。

     

    /********************************************************************

     * idobjc_msgSend(idself, SELop, ...)

     * On entry: a1 is the message receiver,

     *                  a2 is the selector

     ********************************************************************/

     

    ENTRY objc_msgSend

    # check whether receiver is nil

    teq     a1, #0

    moveq   a2, #0

    bxeq    lr

     

    teq 指令说明:

    TEQ RnOperand2 The TEQ instruction performs a bitwise Exclusive OR operation on the value in Rn and the value of Operand2.

    测试 self 是否为空。

    moveq 指令说明:

    如果self为空,则将 selector 也设置为空。

    bx 指令说明:

    在 arm 中 bx lr 用来返回到调用子程序的地方(即:返回到调用者),此处是:如果 self 为空,就返回到调用 objc_msgSend 的地方继续执行。

      如果传递给 objc_msgSend 的 self 参数是 nil,该函数不会执行有意义的操作,直接返回。

        向nil发送消息

        在Objective-C中向nil发送消息是完全有效的——只是在运行时不会有任何作用。Cocoa中的几种模式就利用到了这一点。发向nil的消息的返回值也可以是有效的:
        • 如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如:Person * motherInlaw = [ aPerson spouse] mother]; 如果spouse对象为nil,那么发送给nil的消息mother也将返回nil。
        • 如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者long long的整型标量,发送给nil的消息将返回0。
        • 如果方法返回值为结构体,正如在《Mac OS X ABI 函数调用指南》,发送给nil的消息将返回0。结构体中各个字段的值将都是0。其他的结构体数据类型将不是用0填充的。
        • 如果方法的返回值不是上述提到的几种情况,那么发送给nil的消息的返回值将是未定义的。
        
     

    2.2、 解析

       NSObject *obj = nil; 空指针
        NSLog(@"%@",obj); =>null
        NSObject *obj2 = [obj mutableCopy]; nil调用方法 无效操作  obj2依旧是空指针;空指针的值是null;
        NSLog(@"%@",obj2); =>null
        NSMutableArray *array = [[NSMutableArray alloc] init];  
        [array addObject:obj];  =>crash   
        NSLog(@"%@",array);
     

    3、具体分析nil、Nil、NULL到底是什么!

    首先要说明的是,nil、Nil、NULL三个关键字和NSNull类都是表示空,只是用处不一样,具体的区别如下:

    一、NULL

    1、声明位置

    stddef.h文件

    2、定义

    #undef NULL
    #ifdef __cplusplus
    #  if !defined(__MINGW32__) && !defined(_MSC_VER)
    #    define NULL __null
    #  else
    #    define NULL 0
    #  endif
    #else
    #  define NULL ((void*)0)
    #endif
    其中__cplusplus表示是不是C++代码,所以对于普通的iOS开发者来说,通常NULL的定义就是:
    #  define NULL ((void*)0)

    因此,NULL本质上是:(void*)0

    3、用处及含义

    NULL表示C指针为空

    4、示例

    char *string = NULL;

    二、nil

    1、声明位置

    objc.h文件

    2、定义

    #ifndef nil
    # if __has_feature(cxx_nullptr)
    #   define nil nullptr
    # else
    #   define nil __DARWIN_NULL
    # endif
    #endif
    其中__has_feature(cxx_nullptr)用于判断C++中是否有nullptr特性,对于普通iOS开发者来说,nil的定义形式为:
    #   define nil __DARWIN_NULL
    就是说nil最终是__DARWIN_NULL的宏定义,__DARWIN_NULL是定义在_types.h中的宏,其定义形式如下:
     
    #ifdef __cplusplus
    #ifdef __GNUG__
    #define __DARWIN_NULL __null
    #else /* ! __GNUG__ */
    #ifdef __LP64__
    #define __DARWIN_NULL (0L)
    #else /* !__LP64__ */
    #define __DARWIN_NULL 0
    #endif /* __LP64__ */
    #endif /* __GNUG__ */
    #else /* ! __cplusplus */
    #define __DARWIN_NULL ((void *)0)
    #endif /* __cplusplus */
    非C++代码的__DARWIN_NULL最终定义形式如下:
    #define __DARWIN_NULL ((void *)0)
    也就是说,nil本质上是:(void *)0

    3、用处及含义

    用于表示指向Objective-C中对象的指针为空

    4、示例

     
    NSString *string = nil;
    id anyObject = nil;

    三、Nil

    1、声明位置

    objc.h文件

    2、定义

     
    #ifndef Nil
    # if __has_feature(cxx_nullptr)
    #   define Nil nullptr
    # else
    #   define Nil __DARWIN_NULL
    # endif
    #endif
    和上面讲到的nil一样,Nil本质上也是:(void *)0

    3、用处及含义

    用于表示Objective-C类(Class)类型的变量值为空

    4、示例

    Class anyClass = Nil;

    四、NSNull

    1、声明位置

    NSNull.h文件

    2、定义

     
    @interface NSNull : NSObject <NSCopying, NSSecureCoding>
    
    + (NSNull *)null;
    
    @end

    3、用处及含义

    从定义中可以看出,NSNull是一个Objective-C类,只不过这个类相当特殊,因为它表示的是空值,即什么都不存。它也只有一个单例方法+[NSUll null]。该类通常用于在集合对象中保存一个空的占位对象。

    4、示例

    我们通常初始化NSArray对象的形式如下:
    NSArray *arr = [NSArray arrayWithObjects:@"wang",@"zz",nil];
    当NSArray里遇到nil时,就说明这个数组对象的元素截止了,即NSArray只关注nil之前的对象,nil之后的对象会被抛弃。比如下面的写法:
     
    NSArray *arr = [NSArray arrayWithObjects:@"wang",@"zz",nil,@"foogry"];
    这是NSArray中只会保存wang和zz两个字符串,foogry字符串会被抛弃。
    这种情况,就可以使用NSNull实现:
     
    NSArray *arr = [NSArray arrayWithObjects:@"wang",@"zz",[NSNull null],@"foogry"];


    五、总结

    从前面的介绍可以看出,不管是NULL、nil还是Nil,它们本质上都是一样的,都是(void *)0,只是写法不同。这样做的意义是为了区分不同的数据类型,比如你一看到用到了NULL就知道这是个C指针,看到nil就知道这是个Objective-C对象,看到Nil就知道这是个Class类型的数据。

     
  • 相关阅读:
    MFC开发编程规范(二)
    Mysql日期和时间函数大全(转)
    php获取客户端IP地址的几种方法
    postgres 查看数据表和索引的大小
    PHP应用memcache函数详解
    css自动截取文字 兼容IE firefox Opera
    JavaScript在IE和Firefox浏览器下的7个差异兼容写法小结
    Zend_Auth与Zend_Acl访问控制链
    去除所有js,html,css代码问题
    [转]那些相见恨晚的 JavaScript 技巧
  • 原文地址:https://www.cnblogs.com/xiaowuqing/p/7338170.html
Copyright © 2011-2022 走看看