Mit diesem:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *(ar+1) = &foo;
   ar[1]->c = 'c'; //this work
  (*(*ar+1)).c = 'c'; //this does't work

   return 0;
}
        //(**(ar+1)).c='c'; --> first case

Warum funktioniert das oben genannte nur bei der Variante mit Array-Eintrag und nicht mit Zeiger-Dereferenzierung?

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *ar=malloc(0);
   *(ar+1) = &foo;
   //(**(ar+1)).c='c';
   (*(*ar+1)).c='c'; // NOW IT WORKS --> second case
   printf("%c\n", (*(*ar+1)).c); //prints 'c'

   return 0;
}

Jetzt sind sogar 0 Bytes zugewiesen, das spielt keine Rolle, da ich nur eine vom Betriebssystem bereitgestellte Adresse haben möchte, damit das erste Element initialisiert wird

Frage: Wie funktioniert die Zeigerarithmetik in beiden Fällen? Wie ich sie verstehe:

1) zuerst Um zum Wert von struct Test zu gelangen, geht der Zeiger direkt von der angegebenen Adresse von ar zum Wert von **ar - sizeof(struct Test**)

2) Im zweiten Fall hat der Zeiger das erste Element ar[0] initialisiert, also beginnt er hier *ar und geht mit *ar - sizeof(struct Test*) zum l-Wert.

Aber beide Zeiger haben die gleiche Größe sizeof(struct Test**) == sizeof(struct Test*) und sollten daher keinen Unterschied in der Arithmetik darstellen, oder mir fehlt etwas?

0
Herdsman 8 Mai 2020 im 01:22

3 Antworten

struct Test **ar;
ar=malloc(16);
...
(*(*ar+1)).c = 'c'; //this does't work

Natürlich nicht. Wie in meinem Kommentar erwähnt, hat * eine höhere Priorität als + C. Vorrang des Bedieners. Was passiert also in (*(*ar+1)).c? Ansehen:

(*ar+1)

Was äquivalent ist zu:

ar[0] + 1

Da der Typ für ar ein Zeiger auf Zeiger auf struct Test ist, ist *ar oder ar[0] Geben Sie Zeiger auf struct Test ein. Dann fügen Sie + 1 hinzu, wodurch sizeof (struct Test) zu ar hinzugefügt wird, wenn Sie sizeof (a_pointer) zu ar hinzufügen möchten, um den nächsten Zeiger NICHT die nächste Struktur .

2
David C. Rankin 7 Mai 2020 im 22:57

Für den Anfang sollten Sie die Größe des zugewiesenen Speichers korrekt angeben

   ar = malloc( 2 * sizeof( struct Test * ) );

Diese Aussage

*(ar+1) = &foo;

Setzt das zweite Element des zugewiesenen Zeigerarrays auf die Adresse der globalen Variablen foo.

Es ist das gleiche wie

ar[1] = &foo;

Dieser Ausdruck

*ar

Das entspricht dem Ausdruck

ar[0]

Gibt das erste Element des zugewiesenen Zeigerarrays an. Es wurde nicht initialisiert. Als Ergebnis dieser Ausdruck

*ar+1

Oder

ar[0] + 1

Ruft undefiniertes Verhalten auf (Hinzufügen von 1 zu etwas, das nicht initialisiert wurde und einen unbestimmten Wert hat).

Es scheint, du meinst

(**(ar+1)).c = 'c';

Das ist der Ausdruck

*( ar + 1 )

Gibt das zweite Element des zugewiesenen dynamischen Array von Zeigern an. Bei einer Dereferenzierung erhalten Sie die Adresse des Objekts foo. Dereferenzierung beim zweiten Mal, wenn Sie den Wert des Objekts foo selbst erhalten.

Achten Sie darauf, dass der Ausdruck

ar[1]

Ist äquivalent zu

*( ar + 1 )

Und wie Sie aus dieser gültigen Aussage sehen können

ar[1]->c = 'c'

Der obige Ausdruck ergibt einen Zeiger. Sie müssen es also dereferenzieren, wenn Sie den Operator verwenden möchten.

**( ar + 1 )
1
Vlad from Moscow 7 Mai 2020 im 22:56

Wenn Sie dereferenzieren möchten, um ar[i] zu erhalten, gehen Sie wie folgt vor:

(*(ar+1))->c = 'c';
0
Hitokiri 7 Mai 2020 im 22:29