【问题标题】:How can we pass whole array in #define as argument?我们如何在#define 中传递整个数组作为参数?
【发布时间】:2015-03-24 10:09:25
【问题描述】:

我对一种语法感到困惑,只是想知道以下两种语法之间的区别。

#define objKeys @[@"key1",@"key2",@"key3"]
#define dicWithValue1(val1,val2,val3) [NSMutableDictionary dictionaryWithObjects:@[val1,val2,val3] forKeys:objKeys]
#define dicWithValue2(objArray) [NSMutableDictionary dictionaryWithObjects:objArray forKeys:objKeys]

-(void)someFunction
{
    NSMutableArray *arrValues = [[NSMutableArray alloc] init];

    [arrValues addObject:dicWithValue1(@"val1",@"val2",@"val3")];  // STATEMENT 1
    [arrValues addObject:dicWithValue1(@[@"val1",@"val2",@"val3"])]; // STATEMENT 2

    // Below Statements will give error... for Multiple Arguments..
    [arrValues addObject:dicWithValue2(@"val1",@"val2",@"val3")];  // STATEMENT 3
    [arrValues addObject:dicWithValue2(@[@"val1",@"val2",@"val3"])]; // STATEMENT 4

}

问题 1:语句 2 会在运行时使应用程序崩溃,但在编译时没有给出任何错误。那么,Statement 1 和 Statement 2 有什么区别呢?

问题 2:我们如何在 #define 函数中传递数组对象,作为语句 3 和 4 给出多个参数的编译错误。

【问题讨论】:

    标签: ios objective-c syntax c-preprocessor


    【解决方案1】:

    首先提示,您可以使用 gcc -E 对文件运行预处理器,这将扩展您的所有宏,以便轻松查看问题所在:

    gcc -E -o outfile.m myFile.m

    如果您将编写的代码放入文件中并运行此命令,您将获得与您的问题相关的所有错误消息。如果您对错误消息有任何疑问,可以提问。

    由于宏无法忽略逗号,因此您对正在执行的某些操作感到困惑。所以@[@"val1",@"val2",@"val3"] 将三个参数传递给宏,即 arg1:@[@"val1"arg2:@"val2"arg3:@"val3"] 你可以用括号解决这个问题:

    (@[@"val1", @"val2", @"val3"])

    [arrValues addObject:dicWithValue2((@[@"val1",@"val2",@"val3"]))]; \\Statement 4
    

    Here's 包含有关逗号问题部分的文档。

    【讨论】:

      【解决方案2】:

      问题一:

      语句 2 将崩溃,因为您有不同数量的键和值。编译器不知道数组中的元素个数应该相等,也没有办法找出来;因此这是一项只能在运行时强制执行的要求。

      问题 2:

      我真的不明白语句 1 已经显示了如何从编译器常量作为数组传递的问题。我建议你避免使用如此复杂的宏,因为它们可能比它们的价值更麻烦。

      【讨论】:

        【解决方案3】:

        问题 1:

        dicWithValue1 期望三个值。

        语句 1 会这样做,但语句 2 不会(它传递一个值,该值是一个由 3 个对象组成的数组)。

        您可以使用语句 1 或语句 4。

        问题 2:

        编译错误说明是什么?

        您可能需要在此处将 objArray 转换为数组:dictionaryWithObjects:objArray

        【讨论】:

          【解决方案4】:

          我认为@trojanfoe 是对的。

          答案 1:

          语句 2 将失败,因为直到运行时才定义参数数量,而且它仍然会崩溃,因为您只传递一个参数而不是三个参数。

          答案 2:

          语句 3 不正确,原因与上述相同,即您传递的参数数量无效。 语句 4 也将不起作用,因为直到运行时才定义参数数量。

          但是,您可以尝试使用此代码使其工作:

          NSArray* tempArray= [[NSArray alloc] initWithObjects:@"abc", @"def", @"ghi", nil];
          [arrValues addObject:dicWithValue2(tempArray)];
          

          【讨论】:

            【解决方案5】:

            我相信答案在于编译器如何解析宏声明中的参数数据类型和参数数量的机制。我不是该主题的专家,但似乎编译器在编译时解析函数的参数数量存在一些问题。

            在语句 2 中,如果您减少/增加 1 个参数,编译器将针对不匹配的参数抛出错误。虽然它只是一个参数,并且在运行时会在崩溃时得到确认,因为剩余的两个参数是nil。 Statement2 没有提供函数所期望的确切参数编号。这就是崩溃的原因。

            出于同样的原因,编译器无法计算语句 3 和 4 中的参数计数。

            就您的问题 2 解决方案而言,您可以通过创建本地数组对象然后将其作为参数传递来将 NSArray 对象传递给 macro。请看下面的代码:-

            NSArray * arrNewValues = @[@"val1",@"val2",@"val3"];
            [arrValues addObject:dicWithValue2(arrNewValues)];
            

            通过这种方式,您可以通过完全匹配的参数使编译器静音。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-08-11
              • 1970-01-01
              • 2011-02-25
              • 2021-06-02
              • 2020-08-22
              • 2013-09-18
              • 1970-01-01
              相关资源
              最近更新 更多