NS_REQUIRES_NIL_TERMINATION(宏)

作者: 曾迦 | 来源:发表于2015-11-05 13:04 被阅读2583次
    #if !defined(NS_REQUIRES_NIL_TERMINATION)
        #if TARGET_OS_WIN32
            #define NS_REQUIRES_NIL_TERMINATION
        #else
            #if defined(__APPLE_CC__) && (__APPLE_CC__ >= 5549)
                #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0,1)))
            #else
                #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel))
            #endif
        #endif
    #endif
    

    attribute((sentinel)) 告知编译器 需要一个结尾的参数,告知编译器参数的列表已经到最后一个不要再继续执行下去了

    例子

    + (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
    

    原理

    
    + (instancetype)arrayWithObjects:(id)firstObj, ...{
    
     NSMutableArray* arrays = [NSMutableArray array];
        //VA_LIST 是在C语言中解决变参问题的一组宏
        va_list argList;
        
        if (firstObj) {
            [arrays addObject:firstObj];
            // VA_START宏,获取可变参数列表的第一个参数的地址,在这里是获取firstObj的内存地址,这时argList的指针 指向firstObj
            va_start(argList, firstObj);
            // 临时指针变量
            id temp;
            // VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数
            // 首先 argList的内存地址指向的fristObj将对应储存的值取出,如果不为nil则判断为真,将取出的值房在数组中,
                并且将指针指向下一个参数,这样每次循环argList所代表的指针偏移量就不断下移直到取出nil
            while ((temp = va_arg(argList, id))) {
                [arrays addObject:temp];
                    NSLog(@"%@",arrays);
            }
    
        }
      // 清空列表
      va_end(argList)
       return arrays;
    }
    

    由上述实例可见,如果在使用 + (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;方法中不传入nil值在(temp = va_arg(argList, id))这个函数中便会一直取出值,在C语言中指针指向的即便是一个空内存地址未初始化也是会取出值的,那么一个基本数据类型的随机数则赋值给了 temp 在添加到数组中,则造成将未初始化的内存空间赋值给可变数组的问题程序出现了崩溃.所以我们在使用+ (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;方法时在多参数的结尾一定要加上nil.

    相关文章

      网友评论

      • Lol刀妹:想请教一下在实际项目中我们什么时候需要用到这个宏
      • 7a946bf5d2ca:结尾部分不用调一下 va_end(argList) 这个函数吗
        曾迦:@大博哥 要加的。
      • ChangeWorld:结尾部分不用调一下 va_end(argList) 这个函数吗
        曾迦:@大博哥 要加
        曾迦:@ChangeWorld 要的忘记加了多谢 现在刚看到
        7a946bf5d2ca:@ChangeWorld 同问 +1
      • e25845d04328:我是才开始学IOS的!不是很懂!不知道以后可不可以提问题?
        曾迦:@e25845d04328 文章中不太明白的可以评论中提,其他的地方简信吧...不过可能不会太及时的回复.

      本文标题:NS_REQUIRES_NIL_TERMINATION(宏)

      本文链接:https://www.haomeiwen.com/subject/wraqhttx.html