Qualche dubbio sugli array di puntatori

di il
6 risposte

Qualche dubbio sugli array di puntatori

Ciao a tutti,
stavo sperimentando un po' gli array di puntatori. Per intenderci qualcosa del genere:

char *lista[2];

Credo di intuire il problema, ma ho bisogno di una conferma o di una smentita e come nel ovviare a quello che sto cercando di seprimentare.

Prima di arrivare al punto cruciale esporrò un'analogia con un esempio che si potrebbe dire un po' "rovesciato" rispetto a quello in questione. Utilizzo come primo esempio i parametri ricevuti dalla funzione main. E leggo i parametri passati leggendo carattere, per carattere attraverso l'aritmetica dei puntatori e tutto funziona secondo quanto previsto:

#include <stdio.h>

int main(int argc, char *argv[])
{
    if(argc == 1)
    {
        int colonna = 0;
        while(*(*(argv) + colonna) != '\0')
        {
            printf("%c",*(*(argv) + colonna));
            colonna++;
        }
        printf("\n");
    }
    else
    {
        int colonna = 0;
        for(int i=0;i<argc;i++)
        {
            colonna = 0;
            while(*(*(argv + i) + colonna) != '\0')
            {
                printf("%c",*(*(argv + i) + colonna));
                colonna++;
            }
            printf(" ");
        }
        printf("\n");
    }
    return 0;
}

Quindi come al solito posso scorrere le "righe" dell'array incrementando la sua locazione tanti quanti sono i parametri passati (argv+i). Ovviamente ogni incremento di "i" è la locazione di memoria ove è salvato un secondo puntatore. Dunque per recuperare il puntatore alla iesima posizione effettuerò: *(argv+i). Essendo anche questo un puntatore posso a questo punto muovermi lungo le locazioni (colonne) utilizzando tale aritmetica: *(argv + i)+colonna. Ovviamente rappresenta una successione di locazioni di memoria, pertanto se voglio visualizzare il contenuto di ciascuno utilizzero ancora l'operatore di deferenza. Pertanto avrò:

 printf("%c",*(*(argv + i) + colonna));

Adesso vengo al dunque del mio problema. Supponiamo di dichiarare il seguente array di puntatori:

char *line[2];
E di volerlo popolare. Intuisco che l'approccio che sto per presentare non può essere corretto, ma ottengo un risultato parzialmente inatteso, del quale vorrei comprendere il motivo.

Primo esempio funzionante

#include <stdio.h>

int main(int argc, char *argv[])
{
     char *line[2]; 
     /** Valorizzo l'indice uno */
    *(*(line+0)+0) = 'P';
    *(*(line+0)+1) = 'l';
    *(*(line+0)+2) = 'u';
    *(*(line+0)+3) = 't';
    *(*(line+0)+4) = 'o';
    *(*(line+0)+5) = '\0';
    
    printf("%s\n",line[0]); /** Stampo la stringa del primo puntatore utilizzando gli indici dei vettori */
    
    /** Stampo la stringa del primo puntatore utilizzando l'aritmetica dei puntatori */
    printf("%c%c%c%c%c%c\n",*(*(line+0)+0),*(*(line+0)+1),*(*(line+0)+2),*(*(line+0)+3),*(*(line+0)+4), *(*(line+0)+5));

    return 0;
}
Adesso espongo il secondo caso (tento di valorizzare l'indice 2 del vettore di puntatori.

#include <stdio.h>

int main(int argc, char *argv[])
{

     char *line[2]; 
     
    *(*(line+0)+0) = 'P';
    *(*(line+0)+1) = 'l';
    *(*(line+0)+2) = 'u';
    *(*(line+0)+3) = 't';
    *(*(line+0)+4) = 'o';
    *(*(line+0)+5) = '\0';
    
    
    *(*(line+1)+0) = 'V';
    *(*(line+1)+1) = 'a';
    *(*(line+1)+2) = 'l';
    *(*(line+1)+3) = 'e';
    *(*(line+1)+4) = '\0';

   
    printf("%s\n",line[0]);
    printf("%c%c%c%c%c%c\n",*(*(line+0)+0),*(*(line+0)+1),*(*(line+0)+2),*(*(line+0)+3),*(*(line+0)+4), *(*(line+0)+5));
    printf("============================\n");
    printf("%s\n",line[1]);
    printf("%c%c%c%c%c%c\n",*(*(line+1)+0),*(*(line+1)+1),*(*(line+1)+2),*(*(line+1)+3),*(*(line+1)+4));
    return 0;
}
Come si potrà notare il frammento va in Segmentation fault quando cerco di valorizzare i "puntatore" nell'indice dell'array di puntatori. Quello che ipotizzo che l'indice 1 dell'array punti a una locazione di memoria "nulla", ma perché l'indice 0 no?

Per fugare questo dubbio eseguo il seguente codice:

#include <stdio.h>

int main()
{
    char *line[2]; 

    printf("%x\n", *line);
    printf("%x\n", *(line+1));
    return 0;
}
E in effetti ottengo un risultato del genere:
da602250
0
Quindi l'indice 1 dell'array punta un puntatore "nullo". Può tornarmi, ma perché il primo indice contiene un puntatore inizializzato?

In realtà questo codice dovrebbe essere effettuato con allocazione dinamica?

Grazie per la pazienza e per le vostre considerazioni e insegnamenti.
Un saluto a tutti.

6 Risposte

  • Re: Qualche dubbio sugli array di puntatori

    Attenzione ... tu usi due puntatori a char che non puntano ad aree di memorie allocate.

    I valori dei due puntatori sono casuali.

    Questo ti porta a sicuro segmentation fault.
  • Re: Qualche dubbio sugli array di puntatori

    oregon ha scritto:


    Attenzione ... tu usi due puntatori a char che non puntano ad aree di memorie allocate.

    I valori dei due puntatori sono casuali.

    Questo ti porta a sicuro segmentation fault.
    Grazie Oregon,
    come dicevo era quello che sospettavo e volevo "dimostrare". Ma la domanda è come mai sistematicamente il primo è allocato? Forse comportamento del compilatore (GCC)?

    Quindi il corretto utilizzo è di utilizzare allocazione dinamica? Si supponga l'immaganizzazione di stringhe di lunghezza variabile, durante la digitazione di un testo...

    Grazie mille Oregon!
  • Re: Qualche dubbio sugli array di puntatori

    Non c'è nulla di allocato. Perché dici questo?

    E' come se scrivessi

    char *pnt1;
    char *pnt2;

    e poi lavorassi con i due puntatori che non puntano a memoria non allocata e hanno un valore casuale.
    La differenza è che questi sono due puntatori singoli, quelli che hai usato due puntatori in un vettore.
  • Re: Qualche dubbio sugli array di puntatori

    oregon ha scritto:


    Non c'è nulla di allocato. Perché dici questo?

    E' come se scrivessi

    char *pnt1;
    char *pnt2;

    e poi lavorassi con i due puntatori che non puntano a memoria non allocata e hanno un valore casuale.
    La differenza è che questi sono due puntatori singoli, quelli che hai usato due puntatori in un vettore.

    Sì hai ragione, in effetti quello che ho detto è concettualmente errato. Quello che mi lascia perplesso è che sistematicamente quel pezzo di codice ritorna al primo indice una locazione di memoria (seppur casuale), mentre il sencondo a una locazione "nulla" (indirizzo 0x0).

    Di valorizzare una array di caratteri (strina) alla locazione 0, mentre ovvio come sia vado in fault...


    Mi lascia perplesso perché sistematicamente ottengo che il primo indice punta a qualcosa, seppur di casuale, mentre il secondo alla locazione 0x0...


    Questione di compilatore, o cos'altro? Un mia inutile "pippa". È che sono testardo e vorrei capire questo comportamento. Ma poi per ogni indice devo allocare dinamicamente prelevando carattere per carattere con una getchar.


    Grazie ancora Oregon, un saluto.
  • Re: Qualche dubbio sugli array di puntatori

    I valori dipendono da ciò che succede in memoria durante l'esecuzione e probabilmente una parte dell'area occupata dai puntatori viene azzerata per altri motivi.

    Non ha alcuna importanza.
  • Re: Qualche dubbio sugli array di puntatori

    oregon ha scritto:


    I valori dipendono da ciò che succede in memoria durante l'esecuzione e probabilmente una parte dell'area occupata dai puntatori viene azzerata per altri motivi.

    Non ha alcuna importanza.
    Grazie Oregon,

    Un saluto.
Devi accedere o registrarti per scrivere nel forum
6 risposte