În C, ce înseamnă o declarație de variabilă cu două asteriscuri (**)? (Programare, C, Pointeri)

Scott Davies a intrebat.

Lucrez cu C și sunt un pic ruginit. Sunt conștient de faptul că * are trei utilizări:

  1. Declararea unui pointer.
  2. Dereferențierea unui pointer.
  3. Înmulțirea

Cu toate acestea, ce înseamnă când există două asteriscuri (**) înaintea unei declarații de variabilă:

char **aPointer = ...

Mulțumesc,

Scott

5 răspunsuri
Jacob Relkin

Se declară o pointer la un char pointer.

Utilizarea unui astfel de pointer ar fi pentru a face lucruri precum:

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

Iată un alt exemplu:

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

Utilizarea de ** cu array-uri:

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

[] pe array-uri face în esență aritmetică de pointer pe pointerul din față, astfel încât, în modul în care se utilizează operatorul array[1] ar fi evaluat este următorul:

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

Acesta este unul dintre motivele pentru care indicii tablourilor încep de la 0, deoarece:

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

Comentarii

  • Vă mulțumim pentru răspuns! Care este cazul de utilizare pentru a avea un pointer la un pointer? –  > Por Scott Davies.
  • @Jacob – Este : o sintaxă C validă ? Nu sunt familiarizat cu aceasta. –  > Por Scott Davies.
  • A char ** poate reprezenta, de asemenea, o listă de șiruri de caractere, de ex. argv sau lista de argumente pe care le transmiteți la execvp sau similar. –  > Por mkb.
  • @Matt Acest lucru este adevărat. Ar trebui să adaug un exemplu în acest sens acolo. –  > Por Jacob Relkin.
JeffFerguson

C și C++ permit utilizarea de pointeri care indică pointeri (spuneți asta de cinci ori mai repede). Aruncați o privire la următorul cod:

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

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

Variabila a conține un caracter. Variabila b indică o locație din memorie care conține un caracter. Variabila c indică o locație din memorie care conține un pointer care indică o locație din memorie care conține un caracter.

Să presupunem că variabila a își stochează datele la adresa 1000 (ATENȚIE: exemplele de locații de memorie sunt complet inventate). Să presupunem că variabila b își stochează datele la adresa 2000 și că variabila c își stochează datele la adresa 3000. Având în vedere toate acestea, avem următoarea dispunere a memoriei:

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

Tom

Aceasta înseamnă că aPointer indică un pointer char.

Așadar,

aPointer: pointer to char pointer

*aPointer :pointer to char

**aPointer: char

Un exemplu de utilizare este crearea unei matrice dinamice de șiruri c

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

aPointer vă oferă un char, care poate fi utilizat pentru a reprezenta un șir de caractere cu terminație zero.

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

John Bode

Acesta declară aPointer ca un pointer la un pointer la char.

Declarațiile în C sunt centrate în jurul tipurilor de expresii; denumirea obișnuită pentru aceasta este „declarația imită utilizarea”. Ca un exemplu simplu, să presupunem că avem un pointer la int numit p și dorim să accesăm valoarea întreagă la care acesta indică în prezent. Am putea dereferențiere pointerul cu ajutorul metodei unare * unitar, astfel:

x = *p;

Tipul pointerului expresie *p este int, astfel încât declarația variabilei pointer p este

int *p;

În acest caz, aPointer este un pointer la un pointer la char; dacă dorim să ajungem la valoarea caracterului la care este îndreptată în prezent, va trebui să o dereglementăm de două ori:

c = **aPointer;

Deci, dacă ne luăm după logica de mai sus, declarația variabilei pointer aPointer este

char **aPointer;

pentru că tipul variabilei expresie **aPointer este char.

De ce ați avea vreodată un pointer la un pointer? Acesta apare în mai multe contexte:

  • Doriți ca o funcție să modifice valoarea unui pointer; un exemplu este funcția strtol funcție de bibliotecă, al cărei prototip (din C99) este
    long strtol(const char * restrict str, char ** restrict ptr, int base);  
    

    Al doilea argument este un pointer la un pointer la char; când apelați strtol, treceți adresa unui pointer la char ca al doilea argument, iar după apel acesta va indica primul caracter din șirul de caractere care nu a fost convertit.

  • Rețineți că, în majoritatea contextelor, o expresie de tip „array de N elemente T” este implicit convertită în tipul „pointer la T”, iar valoarea sa este adresa primului element al array-ului. Dacă „T” este „pointer to char”, atunci o expresie de tip „N-element array of pointer to char” va fi convertită în „pointer to pointer to char”. De exemplu:
    
        void foo(char **arr)
        {
          size_t i = 0;
          for (i = 0; arr[i] != NULL; i++)
            printf("%s
    ", arr[i]);
        }
    
        void bar(void)
        {
          char *ptrs[N] = {"foo", "bar", "bletch", NULL};
          foo(ptrs); // ptrs decays from char *[N] to char **
        }
    
    

  • Doriți să alocați în mod dinamic o matrice multidimensională:
    
    #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] = ...;
          }
        }
      }
    }
    

NPE

Acesta este un pointer la un pointer la char.

Tags:,