为什么临时char **参数是非法的?

时间:2018-10-31 12:38:00

标签: c function pointers

我有一个函数f(char **p),我想用最简单的方法来调用它。

我尝试过

char ** p = {"a", "b"};
f(p);

并得到:

  

标量对象在初始化程序中需要一个元素

所以我将其更改为

char * p[2] = {"a", "b"};
f(p);

没问题[只需char * p[] ]也可以。

为什么不能像下面这样即时创建指针数组?

f({"a", "b"});

3 个答案:

答案 0 :(得分:41)

这给出了警告:

char ** p = {"a", "b"};

因为p不是数组。

这也不合法:

f({"a", "b"});

因为表达式中不允许使用花括号,但可以将其用作初始化程序。

可以像使用复合文字那样动态创建数组:

f((char *[]){"a", "b"});

您还可以使用复合文字来初始化临时文件:

char ** p = (char *[]){"a", "b"};

与第一条语句不同,这是有效的,因为文字是char *[2]类型的数组,并且将衰减为char **,可用于初始化此类型的变量。

有关复合文字的更多详细信息,请参见C standard的6.5.2.5节。

答案 1 :(得分:14)

此声明char ** p = {"a", "b"};会触发警告,因为C不知道如何解释{ }花括号的内容:

  • 声明类型char**表示它是单个指向字符的指针
  • { }的内容指定了两项。

您需要通过在花括号前面指定一个类型来告诉C您正在初始化一个指向带有匿名数组初始元素的指针的指针:

char ** p = (char*[]){"a", "b"}

此构造称为“复合文字”。它可以用于声明中,但也可以用作表达式。

注意:如果您打算将类似的数组传递给函数,则需要提供一种确定数组大小的方法。一种方法是传递NULL来“终止”数组,如下所示:

void f(char **p) {
    int i = 0;
    while (*p) {
        printf("%d:%s\n", i++, *p++);
    }
}
int main(void) {
    f((char*[]){"a", "b", NULL});
    return 0;
}

Demo.

答案 2 :(得分:5)

C99和更高版本添加了compound literals正是出于以下目的:动态创建数组和结构
示例:

struct foo {int a; char b[2];} structure;
structure = ((struct foo) {1, 'a', 0});
int *y = (int []) {1, 2, 3};
int *z = (int []) {1}; 

除了标准C99和更高版本之外,GCC还提供此功能作为扩展。
您可以的话

f((char *[]){"a","b"});

(char *[]){"a","b"}是一个复合文字,它可以动态地创建一个指向char的2个指针的数组。