Was macht “[*]” (Sternmodifikator) bedeutet in C? [duplicate]

Lesezeit: 6 Minuten

[*]
Cutsoy

Beim Versuch, einen C11-Parser (für Bildungszwecke) zu implementieren, fand ich das in C11 (S. 470) sondern auch drin C99 (S. 412) (danke Johannes!), die direkter Erklärer ist definiert als:

(6.7.6) direct-declarator:  
    direct-declarator [ type-qualifier-list? * ]

Zuerst dachte ich, dies sei ein Fehler in der Grammatik (die Typenliste sollte nicht optional sein). Als ich dies jedoch in meinem Referenzcompiler (clang) ausprobierte, erhielt ich einen ziemlich unerwarteten Fehler:

int array[*] = { 1, 2, 3 };
// error: star modifier used outside of function prototype

Anscheinend heißt das also (im Klang). Sternmodifikator.

Ich habe schnell gelernt, dass sie nur in Funktionssignaturen verwendet werden können:

void foobar(int array[*])

Sie können jedoch nur in der Deklaration verwendet werden. Der Versuch, es in einer Funktionsdefinition zu verwenden, führt ebenfalls zu einem Fehler:

void foobar(int array[*]) {
    // variable length array must be bound in function definition
}

Soweit ich das beurteilen kann, ist das beabsichtigte Verhalten die Verwendung [*] in der Funktionsdeklaration und verwenden Sie dann eine feste Zahl in der Funktionsdefinition.

// public header
void foobar(int array[*]);

// private implementation
void foobar(int array[5]) {

}

Ich habe es jedoch noch nie gesehen und verstehe den Zweck auch nicht ganz.

  1. Was ist ihr Zweck, warum wurde sie hinzugefügt?
  2. Was ist der Unterschied zu int[]?
  3. Was ist der Unterschied zu int *?

  • Es ist seit C99 in C. Ich glaube, es bedeutet “Platzhalter für die VLA-Nummer hier”. int[][] ist nicht gültig, aber int[][*] ist (in einem nicht definierenden Funktionsprototypen).

    – Johannes Schaub – litb

    4. August 2016 um 19:03 Uhr


  • Sie haben Recht, ich habe vergessen, es zu erwähnen, aber ich habe nach den Fehlern gesucht, die ich von Clang erhalten habe, und sie entsprachen ihrer VLA-Einheitentestsuite. Trotzdem würde ich gerne ihren Zweck erfahren. Vielen Dank!

    – Cutsoy

    4. August 2016 um 19:04 Uhr

  • 22 Aufrufe und dies ist bereits das erste Google-Ergebnis für “c star modifier”. Sie sind auf eine obskure Funktion gestoßen.

    – Annäherung an DarknessFish

    4. August 2016 um 19:10 Uhr

  • Seit wann ist Clang “der Referenz-Compiler”?

    – Benutzer2357112

    4. August 2016 um 19:11 Uhr

  • @ user2357112 Ich glaube nicht, dass er es in irgendeiner spezifischen Eigenschaft gemeint hat, nur dass es der Compiler war, den er persönlich verwendet, um zu überprüfen, ob seine Interpretation des Standards vernünftig ist.

    – Random832

    5. August 2016 um 5:23 Uhr

Benutzeravatar von hackks
hackt

Was ist ihr Zweck, warum wurde sie hinzugefügt?

Zweck wird gesehen, wenn ein zweidimensionales Array variabler Länge als Funktionsparameter verwendet wird. Die Funktion

int foo(int n, int m, int a[n][m])  {...}   

kann wie folgt prototypisiert werden

int foo(int , int, int [][*]);
int foo(int , int, int a[*][*]);
int foo(int , int, int (*a)[*]);
int foo(int n, int, int a[n][*]);
int foo(int , int m, int a[*][m]);
int foo(int , int m, int (*a)[m]);
int foo(int n, int m, int a[n][m]); 

Im Falle eines zweidimensionalen Arrays, wenn es als Funktionsparameter verwendet wird, kann die Größe der zweiten Dimension nicht weggelassen werden. Wenn der Name der ersten Variablen im Funktionsprototypen weggelassen wird, wäre es nicht möglich, die Länge (zweite Dimension) des Arrays anzugeben. Das * gibt den Hinweis, dass die Länge des Arrays durch den zweiten Parameter bestimmt wird.

Was ist der Unterschied zu int[]?
Was ist der Unterschied zu int *?

Im Falle eines 1D-Arrays für die Funktionsdefinition

int bar(int n, int a[n]} {...}  

jeder der folgenden Prototypen ist gültig

int bar (int , int *);
int bar (int , int [*]);
int bar (int , int []);
int bar (int n, int a[]);
int bar (int n, int a[n]);
int bar (int n, int [n]);   

In diesem Fall auch nicht * Noch n ist notwendig, da der Compiler beide behandelt int [*] und int [n] wie int *. Bei einem eindimensionalen Array können Sie also keinen großen Unterschied feststellen.


HINWEIS: Wenn Sie ein Array mit variabler Länge als Funktionsparameter verwenden, ist die Reihenfolge der Parameter wichtig. Reihenfolge der Parameter für die ersten vier Prototypen von bar kann umgeschaltet werden, aber in den letzten beiden darf der erste Parameter nicht das Array selbst sein.

int bar (int a[n], int n);  //Wrong. Compiler has not yet seen 'n'.
  

  • Dies beantwortet die Frage direkt, anstatt nur einen Standard zu zitieren.

    – alvits

    4. August 2016 um 19:15 Uhr

  • Das Standardzitat beantwortet die Frage direkt und ist maßgeblich, weil es aus dem Standard stammt. Gegen Standardzitate ist nichts einzuwenden. (Wenn ich darüber nachdenke, stammt dieses Zitat aus dem Begründungsdokument, nicht aus dem Standard.)

    – Benutzer2357112

    4. August 2016 um 19:18 Uhr


  • @ user2357112 Es gab eine andere Antwort, die nicht von mir stammte und den Standard direkt zitierte. Ich denke, Alvits bezieht sich darauf. Meiner zitiert nicht den C-Standard, wie Sie richtig darauf hinweisen

    – Johannes Schaub – litb

    4. August 2016 um 19:22 Uhr

  • int bar (int [*], int); ist richtig.

    – MM

    5. August 2016 um 4:30 Uhr

  • Es ist nicht so, dass es etwas gibt falsch mit Zitieren der Norm, an sich. Tatsächlich ist es normalerweise eine gute Idee. Das Problem tritt auf, wenn die Antwort nur aus einem Zitat aus dem Standard ohne jegliche Erklärung besteht. Wenn jemand genau lesen und verstehen könnte, was mit dem Standard gemeint ist, würde er im Allgemeinen keine Frage dazu auf Stack Overflow stellen. Eine gute Antwort (auf eine relevante Frage) muss also wirklich beides leisten. Wenn Sie sich für das eine oder andere entscheiden müssten, müsste ich alvits zustimmen und sagen, dass eine Erklärung einem Zitat überlegen ist.

    – Cody Grey

    5. August 2016 um 4:38 Uhr

Johannes Schaub - Benutzerbild der litb
Johannes Schaub – litb

Das C-Begründungsdokument für C99 sagt

Ein Funktionsprototyp kann Parameter haben, die Array-Typen mit variabler Länge (§6.7.5.2) haben, wobei eine spezielle Syntax wie in verwendet wird

int minimum(int, int [*][*]);

Dies steht im Einklang mit anderen C-Prototypen, bei denen der Name des Parameters nicht angegeben werden muss.


Was ist der Unterschied zu int[]

Was ist der Unterschied zu int *.

Ich denke, es ist einfach so, dass diese Typen in einem Funktionsprototyp “Zeiger” bedeuten, während a [*] in einer Nicht-Spitzenposition (int[*] immer noch gleich int[] Ich denke, in einem Funktionsprototypen) ist tatsächlich gültig und meint Reihe

// not recommended though: it is now unclear what the parameters
// mean to human callers!
void f(int, int [][*]);

void f(int n, int x[][n]) {
    x[1][0] = 1;
}

int main() {
   int a[2][1];
   f(1, a);
   printf("%d\n", a[1][0]);
}

Zu diesem Zweck muss der Compiler beim Indizieren des Arrays in der Funktionsdefinition wissen, wie viele Ganzzahlen des nächsten Indexes übersprungen werden müssen, wenn der erste Index angegeben wird (x[i] springt i * n ganze Zahlen ein f Oben). Diese Informationen werden jedoch in der nicht definierenden Prototypdeklaration nicht benötigt, daher können sie weggelassen und durch ersetzt werden *.

  • Ihr Funktionsprototyp sollte sein void f(int, int x[][*]). Wenn Sie dem ersten Parameter einen Namen geben, brauchen Sie die nicht *. Der springende Punkt bei dieser Funktion ist, dass Sie altmodische Funktionsprototypen verwenden können, die die Parameter nicht benennen.

    – Benutzer3386109

    4. August 2016 um 19:33 Uhr

  • @ user3386109 hmm, war die Benennung der Parameter in C89 nicht erlaubt? Ich dachte das wäre immer erlaubt? Warum sollte es “altmodisch” sein, Namen wegzulassen? Allerdings ist die Motivation weniger hoch, wenn man den Parameter trotzdem nennt

    – Johannes Schaub – litb

    5. August 2016 um 6:55 Uhr

1416570cookie-checkWas macht “[*]” (Sternmodifikator) bedeutet in C? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy