Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    [C] Puntatori a puntatori

    Ho sempre saputo che un puntatore ad un puntatore, è un' area di memoria, che punta ad un' altra area di memoria, che punta ad una locazione di memoria contenente qualcosa. Di recente ho letto che un' espressione come **void può essere visto non come puntatore a puntatore, ma come array bidimensionale. Non riesco a capire e ad immaginarmi il perchè....

  2. #2
    Ni, non necessariamente un vero e proprio array bidimensionale, ma in generale un "jagged array". Normalmente quello che dici viene implementato come un vettore di puntatori, ciascuno dei quali punta ad un vettore. Tipicamente si fa una cosa di questo genere:
    codice:
    size_t w=10, h=15;
    int ** arr;
    arr=malloc(h*sizeof(int*));
    for(size_t i=0; i<h; i++)
        arr[i]=malloc(w*sizeof(int));
    a questo punto arr punta ad un vettore di 15 puntatori, ciascuno dei quali punta ad un vettore di 10 puntatori; questa roba può in un certo senso essere vista come un array bidimensionale, specie visto che la sintassi per accedere agli elementi è ben quella:
    codice:
    arr[4][7]=42; /* imposta il settimo elemento del quarto vettore */
    (per deallocare:
    codice:
    for(size_t i=0; i<h; i++)
        free(arr[i]);
    free(arr);
    )
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3

    Re: [C] Puntatori a puntatori

    Originariamente inviato da Darèios89
    **void può essere visto non come puntatore a puntatore, ma come array bidimensionale.
    Più vero il contrario: un array bidimensionale è visto come un array di puntatori a puntatori.

    Fermo restando i concetti espressi da MItaly, occorre specificare che nel linguaggio C gli array bidimensionali non esistono, e vengono gestiti - sia quando allocati dinamicamente che staticamente - come array di puntatori ad array e quindi come array di puntatori a puntatori.

    Agli array multidimensionali C-style sono - nel C++ - nettamente preferibili direttamente list, string, vector.
    "Memento audere semper"

    IBM Europe - Italy Group

  4. #4

    Re: Re: [C] Puntatori a puntatori

    Originariamente inviato da Hard*RTOS
    Fermo restando i concetti espressi da MItaly, occorre specificare che nel linguaggio C gli array bidimensionali non esistono, e vengono gestiti - sia quando allocati dinamicamente che staticamente - come array di puntatori ad array e quindi come array di puntatori a puntatori.
    None. In C gli array multidimensionali esistono, e sono un concetto ben distinto dagli array di puntatori. Giusto per dire una differenza fondamentale, lo standard garantisce che gli elementi di un array multidimensionale siano memorizzati in maniera contigua, motivo per cui su un array bidimensionale si può iterare tranquillamente come se fosse un array monodimensionale, cosa che non si può fare con un jagged array. Inoltre, se gli array multidimensionali fossero dei jagged arrays sarebbe possibile convertirli in puntatori multipli, cosa che non è invece possibile fare.
    Qui la questione è spiegata bene (si parla di C++, ma per quanto riguarda gli array concetti sono fondamentalmente gli stessi).
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Il "non esistono" si riferisce al fatto che in C vengono emulati tramite array di puntatori, quindi sintatticamente esistono, in pratica no.
    "Memento audere semper"

    IBM Europe - Italy Group

  6. #6
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,589
    Originariamente inviato da Hard*RTOS
    Il "non esistono" si riferisce al fatto che in C vengono emulati tramite array di puntatori, quindi sintatticamente esistono, in pratica no.
    No, in C non sono affatto un array di puntatori, hanno proprietà completamente diverse, questo voleva dirti MItaly!
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  7. #7
    Originariamente inviato da Hard*RTOS
    Il "non esistono" si riferisce al fatto che in C vengono emulati tramite array di puntatori, quindi sintatticamente esistono, in pratica no.
    codice:
    int a[10][20];
    questo è un array bidimensionale, e non è un array di puntatori.
    codice:
    int (*a)[20]=malloc(10*20*sizeof(int));
    Questo è lo stesso array allocato dinamicamente, e non è un array di puntatori (piuttosto, è un puntatore a vettori, che punta ad un'area di memoria che viene usata come vettore di vettori). In entrambi i casi, quando scrivo
    codice:
    a[5]
    non ottengo un int *, ma un int[20], che è una cosa ben diversa. Inoltre, in entrambi i casi lo storage è continuo; è garantito che io possa fare
    codice:
    int * b=&(a[0][0]);
    e quindi indicizzare gli elementi con un solo indice (che va da 0 a 199), mentre con un array di puntatori ciò non è possibile.

    Se passo un array multidimensionale ad una funzione devo specificare tutte le dimensioni (tranne al più la prima) dato che l'operatore di subscripting per un array multidimensionale ha bisogno di sapere le dimensioni dei sotto-array per poter raggiungere l'elemento desiderato (con il procedimento descritto a C99 §6.5.2.1, ¶3); con un jagged array questo non è necessario, dato che per ogni dimensione c'è un array di puntatori che indica dove inizia la "riga" della dimensione successiva.
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Ripeto, sintatticamente esistono e possono essere usati; a livello più basso rispetto al codice vengono gestiti come array di puntatori ad array, e quindi come array di puntatori a puntatori; non mi riferisco alle specifiche del linguaggio o a mere definizioni, ma a quanto accade "dietro le quinte".
    "Memento audere semper"

    IBM Europe - Italy Group

  9. #9
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,589
    Ed è appunto quanto accade dietro le quinte che è diverso:

    codice:
    int *a, b[3][3], i, j;
    a = (int*)b;
    for(i = 0; i < 9; i++)
      a[i] = i;
    for(i = 0; i < 3; i++) {
      for(j = 0; j < 3; j++)
        printf("%d ", b[i][j]);
      printf("\n");
    }
    Con un array di array non puoi fare questo! E lo standard serve proprio a definire come vanno le cose "sotto il cofano".
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  10. #10
    Originariamente inviato da Hard*RTOS
    Ripeto, sintatticamente esistono e possono essere usati; a livello più basso rispetto al codice vengono gestiti come array di puntatori ad array, e quindi come array di puntatori a puntatori
    È qui l'errore: dietro le quinte vengono gestiti in maniera diversa.
    Un jagged array funziona con una doppia indirezione - a[i­][j] è *(*(a+i)+j) - mentre un array bidimensionale "vero" va di singola indirezione, dato che le dimensioni delle varie dimensioni sono note e lo storage è contiguo - a[i­][j] è (&a[0][0] + i*N+j), dove N è la lunghezza della riga. Per averne conferma basta guardare lo standard da un lato (vedi il riferimento citato prima), e l'assembly emesso da qualunque compilatore dall'altro.
    E, di nuovo, questo è il motivo per cui un array n-dimensionale non può decadere ad un puntatore n-uplo - questo richiederebbe la generazione di tutti gli array di puntatori "intermedi" che per un "vero" array n-dimensionale non sono richiesti (perché appunto gli elementi sono raggiunti "a colpo" e non con n-upla indirezione).

    Poi ovviamente la regola "as-if" degli standard C e C++ consente al compilatore di fare quel che gli pare dietro le quinte (a patto che il comportamento osservabile sia conforme), ma i constraint che ci sono sugli array multidimensionali (storage contiguo, tutte le dimensioni meno la prima devono essere note) nascono appunto per consentire un'implementazione di questo genere.
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.