wake-up-neo.com

Warum ist ein temporäres char ** Argument illegal?

Ich habe eine Funktion, f(char **p), und ich wollte sie so einfach wie möglich aufrufen.

Ich habe es versucht

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

und bekam:

für ein skalares Objekt ist ein Element im Initializer erforderlich

also habe ich es in geändert

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

und das ging gut [wäre auch gut gewesen mit nur char * p[]].

Warum kann ich nicht wie folgt eine Reihe von Zeigern im laufenden Betrieb erstellen?

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

Dies gibt eine Warnung:

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

weil p kein Array ist.

Dies ist auch nicht legal:

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

da geschweifte Klammern für sich allein in einem Ausdruck nicht zulässig sind (aber als Initialisierer verwendet werden können).

Es ist möglich, ein Array mit einem zusammengesetzten Literal im laufenden Betrieb zu erstellen:

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

Sie können auch ein zusammengesetztes Literal verwenden, um ein temporäres zu initialisieren:

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

Im Gegensatz zur ersten Anweisung ist dies gültig, da das Literal ein Array vom Typ char *[2] Ist und in ein char ** Zerfällt, mit dem eine Variable dieses Typs initialisiert werden kann.

Weitere Informationen zu zusammengesetzten Literalen finden Sie in Abschnitt 6.5.2.5 des C-Standards .

41
dbush

Diese Deklaration char ** p = {"a", "b"}; Löst eine Warnung aus, da C nicht weiß, wie der Inhalt von {} Geschweiften Klammern zu interpretieren ist:

  • Der Deklarationstyp char** Legt nahe, dass es sich um einen einzelnen Zeiger auf Zeiger auf Zeichen handelt
  • Der Inhalt von {} Gibt zwei Elemente an.

Sie müssen C mitteilen, dass Sie einen Zeiger auf einen Zeiger mit einem Zeiger auf das ursprüngliche Element eines anonymen Arrays initialisieren, indem Sie einen Typ vor den geschweiften Klammern angeben:

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

Dieses Konstrukt wird "zusammengesetztes Literal" genannt. Es könnte in einer Deklaration verwendet werden, funktioniert aber auch als Ausdruck.

Hinweis: Wenn Sie vorhaben, ein Array wie dieses an eine Funktion zu übergeben, müssen Sie eine Möglichkeit angeben, um die Größe des Arrays zu bestimmen. Ein Ansatz ist, NULL zu übergeben, um das Array wie folgt zu "terminieren":

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.

14
dasblinkenlight

C99 und höher fügten zusammengesetzte Literale für den genauen Zweck hinzu: Erstellen von Arrays und Strukturen im laufenden Betrieb
Beispiel:

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

Abgesehen von Standard C99 und höher bietet GCC diese Funktion auch als Erweiterung an.
In Ihrem Fall wird dies funktionieren

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

(char *[]){"a","b"} ist ein zusammengesetztes Literal, das im laufenden Betrieb ein Array von 2 Zeigern auf char erstellt.

5
haccks