2016-08-04 40 views
70

Bei dem Versuch, einen C11-Parser (für Bildungszwecke) zu implementieren, fand ich, dass C11 (p. 470) in, sondern auch in C99 (p. 412) (dank Johannes!), Die direkte declarator ist wie folgt definiert:Was bedeutet "[*]" (Sternmodifikator) in C?

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

Zuerst habe ich dachte, dies sei ein Fehler in der Grammatik (die Typliste sollte nicht optional sein). Allerdings, wenn ich das ausprobiert in meinen Referenz-Compiler (Klappern), bekam ich einen ziemlich unerwarteten Fehler:

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

So offensichtlich, (in Klirren) dies den Stern genannt wird Modifikator.

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

void foobar(int array[*]) 

Sie können jedoch nur in der Erklärung verwendet werden. auch versuchen, es in einer Funktionsdefinition führt zu einem Fehler zu verwenden:

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

So soweit ich das beurteilen kann, ist das beabsichtigte Verhalten [*] in der Funktionsdeklaration zu verwenden und dann eine feste Anzahl verwenden in der Funktionsdefinition.

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

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

} 

Aber ich habe es nie gesehen, und ich verstehe nicht ganz den Zweck, es entweder.

  1. Was ist der Zweck, warum wurde es hinzugefügt?
  2. Was ist der Unterschied mit int[]?
  3. Was ist der Unterschied mit int *?
+2

Es ist in C seit C99 gewesen. Ich glaube, es bedeutet "Platzhalter für VLA-Nummer hier". 'int [] []' ist nicht gültig, aber 'int [] [*]' ist (in einem nicht-definierenden Funktionsprototyp). –

+1

Sie haben Recht, ich habe vergessen, es zu erwähnen, aber ich suchte nach den Fehlern, die ich von clang bekommen habe und sie entsprachen ihrer VLA-Unit-Testsuite. Trotzdem würde ich gerne ihren Zweck kennen. Vielen Dank! – elslooo

+1

22 Aufrufe und dies ist bereits das erste Google-Ergebnis für "c star modifier". Sie haben eine obskure Funktion getroffen. – ApproachingDarknessFish

Antwort

14

Die C Begründung Dokument für C99 sagt

A function prototype can have parameters that have variable length array types (§6.7.5.2) using a special syntax as in

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

This is consistent with other C prototypes where the name of the parameter need not be specified.


What's the difference with int[]

What's the difference with int *.

Ich denke, es ist einfach, dass diese Typen in einem Funktionsprototyp bedeutet "Zeiger", während ein [*] in einem nicht top Position (int[*] immer noch gleich int[] Ich denke, in einer Funktion Prototyp) ist tatsächlich gültig und bedeutet Array

// 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]); 
} 

Was den Zweck, wenn sie in der Funktionsdefinition das Array indizieren, muss der Compiler wissen, wie viele Zahlen des nächsten Index zu überspringen, wenn der erste Index (x[i] springt i * n ganzen Zahlen in f oben) geben. Aber diese Information wird in der nicht-definierenden Prototyp-Deklaration nicht benötigt, daher kann sie weggelassen und durch * ersetzt werden.

+1

Ihr Funktionsprototyp sollte 'void f (int, int x [] [*])' sein. Wenn Sie dem ersten Parameter einen Namen geben, brauchen Sie das '*' nicht. Der springende Punkt dieses Features ist, dass Sie altmodische Funktionsprototypen verwenden können, die die Parameter nicht benennen. – user3386109

+0

@ user3386109 hmm, nannte die Parameter in C89 nicht erlaubt? Ich dachte, das war immer erlaubt? Warum sollten die Namen "altmodisch" sein? Aber, stimmt, die Motivation ist weniger hoch, wenn Sie den Parameter sowieso benennen –

38

Zweck wird angezeigt, 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 jeder der

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]); 

Bei zweidimensionaler Anordnung folgende prototypisiert werden, wenn sie als Funktionsparameter, die Größe der zweiten Dimension verwendet wird, kann nicht weggelassen werden. Wenn der Name der ersten Variablen im Funktionsprototyp nicht angegeben wird, ist es nicht möglich, die Länge (zweite Dimension) des Arrays anzugeben. Die * gibt den Hinweis, dass die Länge des Arrays durch den zweiten Parameter bestimmt wird.

What's the difference with int[] ?
What's the difference with int * ?

Bei 1D-Array für die Funktionsdefinition

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

eine der folgenden Prototyp gilt

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 weder * noch n ist notwendig, da Compiler Behandle sowohl int [*] als auch int [n] als int *. Mit einem eindimensionalen Array können Sie also keinen großen Unterschied sehen.

HINWEIS: Bei der Verwendung von Arrays mit variabler Länge als Funktionsparameter ist die Reihenfolge der Parameter wichtig. Die Reihenfolge der Parameter für die ersten vier Prototypen von bar kann umgeschaltet werden, aber in den letzten zwei ersten Parametern darf nicht das Array selbst sein.

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

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

+5

Das Standardzitat beantwortet direkt die Frage und es ist autoritativ, weil es vom Standard ist. Mit Standardangeboten ist nichts falsch. (Denken Sie daran, dass das Zitat aus dem Begründungsdokument stammt, nicht dem Standard.) – user2357112

+0

@ user2357112 Es gab eine andere Antwort, die nicht von mir stammt und die den Standard direkt zitiert. Ich nehme an, dass Alvits sich dazu bekennt. Meine zitiert nicht den C-Standard, wie Sie richtigerweise darauf hinweisen, –