2017-01-31 2 views
1

Imaginons que j'ai 3 différents types de jeux de données dans 3 différents struct:pointeur vide à pointeur struct l'intérieur d'une structure sans déréférencement il

typedef struct 
{ 
    int a; 
    //... 
}DATATYPE1; 

typedef struct 
{ 
    int a; 
    //... 
}DATATYPE2; 

typedef struct 
{ 
    int a; 
    //... 
}DATATYPE3; 

imagine alors je veux un de ces types de données à affecter à un struct principale comme ceci:

typedef struct 
{ 
    int b; 
    void* data; 
    //... 
}OBJECT; 

Say Je déclare OBJECT* abc = malloc(sizeof(OBJECT)); et DATATYPE1* dt1 = malloc(sizeof(DATATYPE1)); Est-il possible que je pourrais alors jeter dans quelque chose de code comme ceci:

abc->data = dt1; 

puis appelez:

(abc->data)->a; 

sans déréférencer le pointeur abc->data retour à e.g. DATATYPE1* dp = abc->data puis utilisez dp->a;

+2

1) N'utilisez pas de noms en majuscules pour autre chose que des macros ou des constantes enum. 2) N'utilisez jamais 'void *' sans véritable besoin. Écrivez un code de type sécurité! 3) Comment le compilateur est-il censé connaître le type de votre "void *" sans un casting? 4) Quel est votre problème ** réel ** que vous essayez de résoudre? – Olaf

+0

C'est le point que je ne connais pas. Mais y a-t-il un moyen de travailler comme ça? – Primemaster

+0

Pourrait? Peut-être (si vous pouviez clarifier le point 4). La vraie question est: ** devriez-vous **?Ce qui est plus facile de répondre: ** NON! ** – Olaf

Répondre

3

Je suppose que le problème est que vous voulez accéder au champ a de vos trois DATATYPE S, sans savoir lequel DATATYPE est réellement présent. La réponse est oui vous pouvez, parce que la spécification C dit explicitement que quel que soit DATATYPE est présent, le pointeur pointe sur le premier membre de la structure, et peut donc être moulé en toute sécurité à ce type.

Voir: Are there any guarantees about C struct order? et surtout:

15 Dans un objet de structure, les éléments de terrain non bits et les unités dans lequel les champs de bit résident ont des adresses qui augmentent dans l'ordre dans lequel ils sont déclarés. Un pointeur vers un objet de structure converti de manière appropriée pointe vers son membre initial (ou si ce membre est un champ de bits , puis vers l'unité dans laquelle il réside) et vice versa. Il peut y avoir un bourrage sans nom dans un objet de structure, mais pas au début .

Par conséquent,

le code suivant vous permet d'accéder à:

OBJECT* abc = malloc(sizeof(OBJECT)); 
abc->data = malloc(sizeof(DATATYPE1)); 
int* pointerToA = (int*) abc->data; 

Que ce soit une bonne pratique de programmation est une autre question, que je ne répondrai pas.

0

Vous devez déclarer tout ce que vous ferez référence dans votre code C. C'est la seule façon pour le compilateur de connaître la taille et l'emplacement de l'objet dans cette adresse spécifique.

Je pense que vous pouvez utiliser des blocs anonymes syndicaux et faire quelque chose comme ceci:

typedef struct 
{ 
    int b; 
    union { 
     void* data; 
     DATATYPE1 *dt1; 
     DATATYPE2 *dt2: 
     DATATYPE3 *dt3; 
    };  
} OBJECT; 

puis utilisez:

OBJECT* abc = (OBJECT*)malloc(sizeof(OBJECT)); 
DATATYPE1* dt1 = (DATATYPE1*)malloc(sizeof(DATATYPE1)); 
abc->data = (void *)dt1; 
int val = abc->dt1->a; 
+0

Aucun de ces moulages n'est nécessaire, mais tout semble correct. Il est difficile de déterminer si cela répond réellement à la question, car le PO semble un peu incertain de ce qu'il veut savoir. Néanmoins, un syndicat peut en effet être un bon moyen pour le PO d'aborder son problème. –

+0

Je suis d'accord avec vous. J'ai essayé de lui montrer ce que je pense qui peut produire le code qui ressemble beaucoup à son désir. Merci d'avoir commenté les moulages, ils ne sont vraiment pas nécessaires. – lewohart