Domanda

    typedef struct unit_class_struct {
        char *name;
    } person;



person * setName() {
       person * array;
       array = malloc (2 * sizeof(person));

       array->name = strdup("Robert");
       array++;
       array->name = strdup("Jose");
       return array;
}


    int main()
    {
        person *array;

        array = setName();

        printf("First name is %s\n", array[0].name);
        printf("Second name is %s\n", array[1].name);

        return 0;
    }

In questo esempio, array [0] .name restituisce Jose, non Robert come mi aspettavo, e array [1] .name è vuoto.

Tuttavia, se uso

person * setName() {
       person * array;
       person * array_switch;
       array = malloc (2 * sizeof(person));
       array_switch = array;
       array_switch->name = strdup("Robert");
       array_switch++;
       array_switch->name = strdup("Jose");
       return array;
}

Funziona come previsto. array.name [0] restituisce Robert e array.name [1] restituisce Jose.

Perché per funzionare questo esempio richiede un secondo puntatore? Posso farlo senza usare un secondo puntatore E usare ancora l'aritmetica del puntatore?

So già che questo è anche un altro modo di farlo:

person * setName() {
       person * array;
       array = malloc (2 * sizeof(person));
       array[0].name = strdup("Robert");
       array[1].name = strdup("Jose");
       return array;
}
È stato utile?

Soluzione

Nel tuo codice:

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   array->name = strdup("Robert");
   array++;
   array->name = strdup("Jose");
   return array;
}

alloca spazio per due elementi nell'array e imposti array in modo che punti al primo:

+-------+      +----------+
| array | ---> | array[0] |
+-------+      +----------+
               | array[1] |
               +----------+

Quindi si incrementa il puntatore dell'elemento con array ++ e che è ciò che viene restituito alla funzione chiamante alla fine. Quel puntatore punta al secondo elemento dell'array, motivo per cui sembra essere sbagliato (e perché quasi sicuramente andrai in crash quando proverai a liberare quella memoria in seguito):

+-------+      +----------+
| array | -+   | array[0] |
+-------+  |   +----------+
           +-> | array[1] |
               +----------+

Ciò di cui hai bisogno è:

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   array[0].name = strdup("Robert");
   array[1].name = strdup("Jose");
   return array;
}

come hai già sottolineato. Questa soluzione non modifica affatto il puntatore array . Ma, se vuoi davvero usare i puntatori, puoi semplicemente invertire le azioni di array ++ con un array-- prima di tornare in modo che array è riportato al valore corretto:

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   array->name = strdup("Robert");
   array++;
   array->name = strdup("Jose");
   array--;
   return array;
}

Oppure, un altro modo, che non cambia il puntatore originale, non usa l'indicizzazione dell'array e non usa un secondo puntatore è usare l'aritmetica del puntatore. Il compilatore sa a quale tipo punta il puntatore, quindi può regolare correttamente il puntatore per trovare l'elemento successivo (sai già che sa come farlo poiché array ++ è una scorciatoia per array = array + 1 e anche quella dichiarazione regola il valore dell'importo corretto):

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   (array+0)->name = strdup("Robert");
   (array+1)->name = strdup("Jose");
   return array;
}

Altri suggerimenti

Fai semplicemente semplici operazioni con i puntatori aritmetici, come addizioni e sottrazioni:

    array->name = "Robert";
    (array+1)->name = "Jose";
    return array;

Un puntatore è letteralmente solo un num (l'indirizzo in memoria). Stai modificando questo puntatore in modo che punti da qualche altra parte, quindi lo restituisci.

Questo utilizzerà l'aritmetica del puntatore e manterrà il puntatore originale dell'array:

person * setName() {
       person * array;

       array = malloc (2 * sizeof(person));
       (array+0)->name = strdup("Robert");
       (array+1)->name = strdup("Jose");

       return array;
}

Si


Poiché hai incrementato array , non hai più un puntatore all'elemento [0] , ma un puntatore al [1] elemento. Fai questo:

   array->name = strdup("Robert");
   array++;
   array->name = strdup("Jose");
   return array - 1;

Tieni presente che in C p [x] non è altro che * (p + x) , o, se vuoi, e pensa a questo: (p + x) [0] . L'ultimo caso è quello che stava facendo effettivamente il tuo programma, con x == 1. Quindi (p + 1) [1] è lo stesso di p [2 ] e non c'è nulla lì, quindi il tuo risultato nullo.

(Puoi anche scriverlo come ...

   array++->name = strdup("Robert");
   array--->name = strdup("Jose");
   return array;

... ma se lo fai, un gruppo di persone verrà e ti voterà. È stato davvero così difficile da leggere? Il nostro obiettivo è davvero quello di scrivere solo codice goffo non ispirato?)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top