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

CIs*_*ies 25 c pointers function

我有一个功能,f(char **p)我想以最简单的方式调用它.

我试过了

char ** p = {"a", "b"};
f(p);
Run Code Online (Sandbox Code Playgroud)

得到了:

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

所以我改成了

char * p[2] = {"a", "b"};
f(p);
Run Code Online (Sandbox Code Playgroud)

并且那很好[ 仅用就好了char * p[] ].

为什么我不能像下面这样动态创建一个指针数组?

f({"a", "b"});
Run Code Online (Sandbox Code Playgroud)

dbu*_*ush 41

这给出了一个警告:

char ** p = {"a", "b"};
Run Code Online (Sandbox Code Playgroud)

因为p不是数组.

这也不合法:

f({"a", "b"});
Run Code Online (Sandbox Code Playgroud)

因为在表达式中不允许花括号(但可以用作初始化器).

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

f((char *[]){"a", "b"});
Run Code Online (Sandbox Code Playgroud)

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

char ** p = (char *[]){"a", "b"};
Run Code Online (Sandbox Code Playgroud)

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

有关复合文字的更多详细信息,请参阅C标准的 6.5.2.5节.

  • 不幸的是,以这种方式创建的任何复合文字都将具有以最近的封闭块结束的生命周期,因此给出`int**p; ... if(someCondition)p =(int*[2]){&x,&y};`在if控制语句周围添加大括号会导致复合文字创建的对象在代码使用之前死掉. (2认同)

das*_*ght 14

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

  • 声明类型char**表明它是一个指向指针的单指针
  • 内容{ }指定两个项目.

您需要通过在大括号前指定类型来告诉C您正在初始化指向指针的指针,指针指向匿名数组的初始元素:

char ** p = (char*[]){"a", "b"}
Run Code Online (Sandbox Code Playgroud)

这种结构称为"复合文字".它可以在声明中使用,但它也可以用作表达式.

注意:如果您计划将类似的数组传递给函数,则需要提供一种确定数组大小的方法.一种方法是传递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;
}
Run Code Online (Sandbox Code Playgroud)

演示.


hac*_*cks 5

C99和更高版本为确切目的添加了复合文字:动态创建数组和结构
示例:

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

除了标准C99及更高版本,GCC也提供此功能作为扩展.
在你的情况下,这将工作

f((char *[]){"a","b"});
Run Code Online (Sandbox Code Playgroud)

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