Was bedeutet in C eine Variablendeklaration mit zwei Sternchen (**)?

Lesezeit: 4 Minuten

Benutzeravatar von Scott Davies
Scott Davis

Ich arbeite mit C und bin etwas eingerostet. Ich bin mir bewusst, dass * hat drei Verwendungen:

  1. Einen Zeiger deklarieren.
  2. Dereferenzieren eines Zeigers.
  3. Multiplikation

Was bedeutet es jedoch, wenn zwei Sternchen (**) vor einer Variablendeklaration:

char **aPointer = ...

Vielen Dank,

Scott

Benutzeravatar von Jacob Relkin
Jakob Relk

Es erklärt a Zeiger auf a char Zeiger.

Die Verwendung eines solchen Zeigers wäre, solche Dinge zu tun wie:

void setCharPointerToX(char ** character) {
   *character = "x"; //using the dereference operator (*) to get the value that character points to (in this case a char pointer
}
char *y;
setCharPointerToX(&y); //using the address-of (&) operator here
printf("%s", y); //x

Hier ist ein weiteres Beispiel:

char *original = "awesomeness";
char **pointer_to_original = &original;
(*pointer_to_original) = "is awesome";
printf("%s", original); //is awesome

Gebrauch von ** mit Arrays:

char** array = malloc(sizeof(*array) * 2); //2 elements

(*array) = "Hey"; //equivalent to array[0]
*(array + 1) = "There";  //array[1]

printf("%s", array[1]); //outputs There

Das [] Operator auf Arrays führt im Wesentlichen Zeigerarithmetik auf dem vorderen Zeiger aus, also der Weg array[1] würde wie folgt ausgewertet werden:

array[1] == *(array + 1);

Dies ist einer der Gründe, warum Array-Indizes beginnen 0Weil:

array[0] == *(array + 0) == *(array);

  • Vielen Dank für Ihre Antwort! Was ist der Anwendungsfall für einen Zeiger auf einen Zeiger?

    – Scott Davies

    30. November 2010 um 21:31 Uhr

  • @Jacob – Ist die: gültige C-Syntax? Das ist mir nicht bekannt.

    – Scott Davies

    30. November 2010 um 21:38 Uhr

  • EIN char ** kann auch eine Liste von Zeichenfolgen darstellen, z argv oder die Liste der Argumente, an die Sie übergeben execvp oder ähnliches.

    – Matt K

    30. November 2010 um 21:49 Uhr

  • @ Matt Das ist wahr. Ich sollte ein Beispiel dafür hinzufügen.

    – Jakob Relkin

    30. November 2010 um 21:50 Uhr

C und C++ erlauben die Verwendung von Zeigern, die auf Zeiger zeigen (sagen wir das fünfmal so schnell). Sehen Sie sich den folgenden Code an:

char a;
char *b;
char **c;

a="Z";
b = &a; // read as "address of a"
c = &b; // read as "address of b"

Die Variable a hält ein Zeichen. Die Variable b zeigt auf eine Stelle im Speicher, die ein Zeichen enthält. Die Variable c zeigt auf eine Stelle im Speicher, die einen Zeiger enthält, der auf eine Stelle im Speicher zeigt, die ein Zeichen enthält.

Angenommen, die Variable a speichert seine Daten unter Adresse 1000 (ACHTUNG: Beispielspeicherplätze sind komplett belegt). Angenommen, die Variable b speichert seine Daten an Adresse 2000, und dass die Variable c speichert seine Daten unter Adresse 3000. Angesichts all dessen haben wir das folgende Speicherlayout:

MEMORY LOCATION 1000 (variable a): 'Z'
MEMORY LOCATION 2000 (variable b): 1000 <--- points to memory location 1000
MEMORY LOCATION 3000 (variable c): 2000 <--- points to memory location 2000

Es erklärt aPointer als Zeiger auf einen Zeiger auf char.

Deklarationen in C konzentrieren sich auf die Typen von Ausdrücke; Der gebräuchliche Name dafür ist “declaration mimics use”. Nehmen wir als einfaches Beispiel an, wir haben einen Zeiger auf int mit dem Namen p und wir wollen auf den ganzzahligen Wert zugreifen, auf den es gerade zeigt. Wir würden Dereferenzierung der Zeiger mit dem unären * Operator, etwa so:

x = *p;

Die Art der Ausdruck *p ist intalso die Deklaration der Zeigervariablen p ist

int *p;

In diesem Fall, aPointer ist ein Zeiger auf einen Zeiger auf char; Wenn wir zu dem Zeichenwert gelangen möchten, auf den er gerade zeigt, müssten wir ihn zweimal dereferenzieren:

c = **aPointer;

Also, nach der obigen Logik, die Deklaration der Zeigervariablen aPointer ist

char **aPointer;

weil die Art der Ausdruck **aPointer ist char.

Warum sollten Sie jemals einen Zeiger auf einen Zeiger haben? Es taucht in mehreren Kontexten auf:

  • Sie möchten, dass eine Funktion einen Zeigerwert ändert; Ein Beispiel ist die strtol Bibliotheksfunktion, deren Prototyp (ab C99) ist
    long strtol(const char * restrict str, char ** restrict ptr, int base);  
    

    Das zweite Argument ist ein Zeiger auf einen Zeiger auf char; wenn du anrufst strtolübergeben Sie als zweites Argument die Adresse eines Zeigers an char, der nach dem Aufruf auf das erste nicht konvertierte Zeichen im String zeigt.

  • Denken Sie daran, dass in den meisten Kontexten ein Ausdruck vom Typ „N-Element-Array von T“ implizit in den Typ „Zeiger auf T“ konvertiert wird und sein Wert die Adresse des ersten Elements des Arrays ist. Wenn “T” “Zeiger auf Zeichen” ist, dann wird ein Ausdruck vom Typ “N-Element-Array von Zeiger auf Zeichen” in “Zeiger auf Zeiger auf Zeichen” konvertiert. Zum Beispiel:
    
        void foo(char **arr)
        {
          size_t i = 0;
          for (i = 0; arr[i] != NULL; i++)
            printf("%s\n", arr[i]);
        }
    
        void bar(void)
        {
          char *ptrs[N] = {"foo", "bar", "bletch", NULL};
          foo(ptrs); // ptrs decays from char *[N] to char **
        }
    
    

  • Sie möchten ein mehrdimensionales Array dynamisch zuweisen:
    
    #define ROWS ...
    #define COLS ...
    ...
    char **arr = malloc(sizeof *arr * ROWS);
    if (arr)
    {
      size_t i;
      for (i = 0; i < ROWS; i++)
      {
        arr[i] = malloc(sizeof *arr[i] * COLS);
        if (arr[i])
        {
          size_t j;
          for (j = 0; j < COLS; j++)
          {
            arr[i][j] = ...;
          }
        }
      }
    }
    

Das bedeutet es aPointer zeigt auf einen char-Zeiger.

So

aPointer: pointer to char pointer

*aPointer :pointer to char

**aPointer: char

Ein Beispiel für seine Verwendung ist das Erstellen eines dynamischen Arrays von C-Strings

char **aPointer = (char**) malloc(num_strings);

aPointer gibt Ihnen ein Zeichendie verwendet werden kann, um eine nullterminierte Zeichenfolge darzustellen.

*aPointer = (char*)malloc( string_len + 1); //aPointer[0]
*(aPointer + 1) = (char*)malloc( string_len + 1); //aPointer[1]

Dies ist ein Zeiger auf einen Zeiger auf char.

1414870cookie-checkWas bedeutet in C eine Variablendeklaration mit zwei Sternchen (**)?

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

Privacy policy