2016-05-20 7 views
6

Ich fummle mit Zeigern in C herum und bin immer noch unsicher bezüglich einiger Grundlagen. Ich kam mit dem folgenden beispielhaften Code auf:C: Zugriff auf (int) via (void *) zeigt auf (void *) zeigt auf (int) durch Typecasting und Dereferenzierung

#include <stdio.h> 

int main(void) 
{ 
    int num = 42;    // we want to access this integer 
    void *vptrB = &num;  // pointer B points to the integer 
    void *vptrA = &vptrB;  // pointer A points to pointer B 
    printf("%d\n", * (int *) * (void **) vptrA); 
    return 0; 
} 

Der Speicher wie folgt aussehen sollte:

scheme

Gibt es Alternativen, um die ganze Zahl zugreifen? Alles schlecht/unsicher mit dem Beispiel? Ist * (int *) * (void **) vptrA die einzige Möglichkeit, über vptrA und vptrB auf num zuzugreifen?

+3

Warum behalten Sie Ihre Zeiger als 'void *' anstelle der richtigen Typen? Sie sollten versuchen, mit * dem Typsystem zu arbeiten, nicht dagegen anzukämpfen. –

+1

Autsch; Erinnere mich daran, deinen Code in Zukunft nicht mehr lesen zu müssen? Das ist schmerzhaft zu verstehen. Wenn Sie 'vptrB' referenzieren können, können Sie es einfacher machen, aber wenn Sie nur auf' vptrA' zugreifen können, dann sieht das, was Sie geschrieben haben, korrekt aus - aber ich habe es nicht an einem Compiler vorbeigeführt, um das zu überprüfen. Ich habe es genauso interpretiert wie ein Compiler. –

+0

Ich würde sagen, es ist ein schlechter Stil, 'void *' im Allgemeinen zu verwenden (besonders an Orten, an denen man leicht einen getippten Zeiger verwenden könnte), und einen sehr schlechten Stil, um die Ebene der involvierten Indirektion zu verschleiern (dh die Adresse eines 'void * 'anstelle von' void ** '). Und normalerweise würde ich es vermeiden, mitten in der Dereferenzierung zu casten, also hätte ich '** ((int **) vptrA)'. – Zastai

Antwort

2

Gibt es Alternativen zum Zugriff auf die Ganzzahl?

int num = 42; 
int *vptrB = &num; 
int **vptrA = &vptrB; 
// All print 42 
printf("%d\n", num); 
printf("%d\n", *vptrB); 
printf("%d\n", **vptrA); 

Alles, was schlecht/unsicher mit dem Beispiel?

Verwendung von void* repräsentieren die Adresse in den Datentyp verliert, Ausrichtung, const und volatile Informationen. void* erfordert die Verwendung von Casting, um anschließend die referenzierten Daten zu interpretieren - dies ist fehleranfällig. Obwohl der Code in seinem Casting korrekt ist, unterliegt er Wartungsfehlern und Codeüberprüfungsfehlern.

+1

mit 'void *' ohne Umwandlungen behält 'const' und' volatile' info. Natürlich können Sie diese Dinge wegwerfen, aber das gilt auch für "int *" –