Warum ein Sternchen verwenden “[*]” anstelle einer Ganzzahl für einen VLA-Array-Parameter einer Funktion?

Lesezeit: 6 Minuten

[*]
hackt

Beim Benutzen Array mit variabler Länge als Parameter in Funktion

int sum(int n, int a[n]);

Es ist leicht zu verstehen, erster Parameter (n) gibt die Länge des zweiten Parameters an (a). Aber mit einem anderen Prototypen gestoßen, der für verwendet wurde VLAs als Parameter

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

ist wirklich schwer zu verstehen, warum * wird stattdessen verwendet n Innerhalb []?

  • Hast du überprüft int sum(int n, int a[]);

    – Midhun MP

    28. Juni 2013 um 18:53 Uhr

  • y@aaronman; Jawohl. seine c99-Funktion.

    – Hacken

    28. Juni 2013 um 18:54 Uhr

  • Also… int a[*] ist ein Array von Zeigern oder ein Array variabler Länge? Es ist nicht einfach zu verstehen, nur Code zu sehen …? Ich meine… ist “int a[*]” dasselbe wie “int *a[]” oder einfach nur “int a[]”?

    – Alejandro Ivan

    28. Juni 2013 um 18:54 Uhr


  • Verwandte/doppelte Frage. Siehe Antwort von Jens Gustedt.

    – ajp15243

    28. Juni 2013 um 19:03 Uhr

  • @hackks Wenn Sie das Ende seiner Antwort lesen, erklärt er im Wesentlichen, was AndreyT unten erklärt, nämlich das [*] ist nützlich, wenn Sie Ihre vorangehenden Längenparameter in Ihren Funktionsprototypen nicht benennen.

    – ajp15243

    28. Juni 2013 um 19:11 Uhr


Benutzer-Avatar
AnT steht zu Russland

Das [*] Syntax soll beim Deklarieren verwendet werden Funktionsprototypen. Das wichtigste Detail hier ist, dass Sie in Funktionsprototypen Ihre Parameter nicht benennen müssen, Sie müssen nur den Typ jedes Parameters angeben.

In Ihrem Beispiel, wenn Sie den ersten Parameter verlassen unbenanntdann können Sie offensichtlich nicht verwenden n in Ihrer zweiten (Array-)Parameterdeklaration. In vielen Fällen müssen Sie dem Compiler jedoch mitteilen, dass ein Parameter ein VLA ist. Dies ist, wenn die [*] Syntax kommt zur Rettung.

Wenn Sie die Parameternamen weglassen, sieht der Prototyp in Ihrem Fall möglicherweise so aus

int sum(int, int [*]);

Es ist jedoch wichtig zu beachten, dass in dein Beispiel: Diese Syntax ist zulässig, aber nicht unbedingt erforderlich. Genau wie bei Nicht-VLA-Arrays, an int [n] Parameter ist immer noch äquivalent zu int * Parameter (auch für nicht konstante n). Dies bedeutet, dass Sie Ihre Funktion einfach als Prototyp erstellen können

int sum(int, int []);

oder als

int sum(int, int *);

und der Prototyp wird immer noch seinen Zweck erfüllen, dh er wird der Funktionsdefinition genau entsprechen. Mit anderen Worten, VLA-Eigenschaften eines als 1D-Array deklarierten Parameters sind völlig belanglos und die [*] Diese Funktion wird bei solchen VLA-Arrays nicht wirklich benötigt.

Das [*] wird in Situationen wichtig, in denen die “variable Anordnung” des Typs nicht verloren geht, wie dies bei 2D-VLA (oder einem Zeiger auf ein VLA) der Fall wäre. ZB eine Funktion definiert als

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

könnte wie folgt prototypisiert werden

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

Alle oben genannten Prototypen stimmen genau mit der Funktionsdefinition überein.

Wenn Sie die Angewohnheit haben, in Funktionsprototypen immer alle Parameter zu benennen, brauchen Sie das natürlich nie [*] Syntax, da Sie den letzten Prototyp in der obigen Liste verwenden können.

PS Auch hier, wie bei allen Arrays in Parameterdeklarationen, die erste [] ist immer belanglos und zerfällt immer zu einem Zeiger, was bedeutet, dass die folgenden auch gültige äquivalente Prototypdeklarationen für das Obige sind sum2d

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

Es ist das zweite [] das ist wirklich wichtig und muss als “variable Länge” deklariert werden.

  • Manchmal können Sie die Parameter in Prototypen nicht einfach benennen. Wenn Sie einen Bibliotheksheader schreiben, möchten Sie vermeiden, dass Namen mit Namen kollidieren, die die Benutzer Ihrer Bibliothek in Präprozessormakros verwenden. Sie müssen also Namen weglassen oder in den reservierten Namensraum eintreten (in Zusammenarbeit mit der Implementierung) oder die Bibliothek einen Teil des Namensraums reservieren lassen (wie bei einem Präfix wie „MyLibrary_“). Die beiden letzteren können hässlich werden.

    – Eric Postpischil

    28. Juni 2013 um 19:21 Uhr

  • @AndreyT; Bitte präzisieren Sie Ihre Aussage The [*] becomes important in situations when the "variable arrayness" of the type is not lost, as would be the case with 2D VLA. in deiner Antwort.

    – Hacken

    28. Juni 2013 um 19:34 Uhr

  • @EricPostpischil; Es springt über den Kopf 🙁

    – Hacken

    28. Juni 2013 um 19:35 Uhr

  • @hackks: Ich beziehe mich auf die Tatsache, dass die erste [] in Array-Parameter-Deklaration in immer verloren. Der Parameter zerfällt zu einem Zeiger. Das gilt für alle Array-Parameterdeklarationen, unabhängig davon, ob es sich um VLA handelt oder nicht. (Ich habe dies in der Antwort angegeben). Die einzige Möglichkeit, dauerhafte, nicht verschwindende Arrays in einen Typ in C zu “injizieren”, besteht darin, ihn zu einem Zeiger auf ein Array zu machen, z int (*p)[5] oder int (*p)[n]. In Parameterdeklarationen entspricht dies der 2D-Array-Deklaration.

    – AnT steht zu Russland

    28. Juni 2013 um 19:44 Uhr


  • @hackks Im Fall eines variablen Arrays, wie int arr[n][m]muss der Compiler die Größe kennen m denn im Falle eines Array-Zugriffs wie arr[2][3]muss es intern in etwas wie konvertieren *(arr + 2 * m + 3) (Beachten Sie die m im Ausdruck). In ANSI C wäre Ihre einzige Option zu bestehen int *arr und mach das *(arr + 1 * m + 1) Teil manuell, aber in C99 können Sie es vom Compiler für Sie erledigen lassen, daher die neue Syntax. Die erste Größe (in diesem Fall n) wird nie benötigt, da seine Elemente immer direkt nebeneinander stehen (sizeof int Bytes in diesem Fall).

    – yyny

    19. Juli 2020 um 13:06 Uhr

Benutzer-Avatar
aaronmann

Wenn Sie den Stern in eine tatsächliche Funktion einfügen, wird dieser Fehler ausgegeben test.c:3: error: ‘[*]’ not allowed in other than function prototype scope. Nach einiger Recherche ist dies tatsächlich eine Möglichkeit, ein VLA in einem Funktionsprototypen zu deklarieren, mit dem * anstelle des Variablennamens. VLA.
Das Problem hier ist, dass, wenn Sie eine Variable anstelle des Sterns für ein VLA einfügen, es Ihnen sagt, dass es nicht deklariert ist, also ist der Stern eine Möglichkeit, die c99 eingebaut hat, um das zu umgehen.

  • @AlejandroIván Nein, das ist eine andere Syntax.

    Benutzer529758

    28. Juni 2013 um 18:58 Uhr

  • Seltsam … scheint, als ob C99 auf diese Weise deklarierte Arrays mit variabler Länge zulässt.

    – Alejandro Ivan

    28. Juni 2013 um 18:59 Uhr

  • @AlejandroIván schau dir den neuen Beitrag an

    – Aaronmann

    28. Juni 2013 um 19:03 Uhr

  • @H2CO3; Welche Syntax ist das? Es ist zu verwirrend, Mann. Wenn Sie wissen, geben Sie bitte eine Antwort.

    – Hacken

    28. Juni 2013 um 19:04 Uhr

  • @hackks Array von ints: int arr[N]; Array von Zeigern auf int: int *arr[N]; – Zeiger-auf-Array-von-ints: int (*ptr)[N]Array variabler Länge: int arr[<non-const expression>]; – VLA in Funktionsargumentliste: das gleiche oder int arg[*];

    Benutzer529758

    28. Juni 2013 um 19:32 Uhr

1385140cookie-checkWarum ein Sternchen verwenden “[*]” anstelle einer Ganzzahl für einen VLA-Array-Parameter einer Funktion?

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

Privacy policy