TSalm writes:Bonjour,
Voici une petite question de noob motivé.
Venant du monde de la POO, j'ai démarrer un pgm en C avec un struct
qui contient les données, et des fonctions qui s'appliquent à ce
struct.
Par exemple, dans le header, j'ai ceci :
/* ---------- HEADER ---------- */
typedef struct
(int data1
,int data2
) MonStruct;
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
Mon problème est que les données("data1" et "data2") de "MonStruct"
pourraient être, par inadvertance (ou plutôt feignantise ;-) ),
directement modifiées sans passer par les fonctions.
Est-il possible de pouvoir déclarer les données "data1" et "data2"
dans l'implémentation (le fichier ".c"), de façon à ce que
l'utilisation de MonStruct ne puisse se faire qu'en passant par les
fonctions ?
D'avance merci pour vos avis ou éventuelles remarques.
Non. Et oui.
/* ---------- MonObjet.h ---------- */
#ifndef MonObjet_h
#define MonObjet_h
typedef void* MonObjet;
TSalm <tsalm@free.fr> writes:
Bonjour,
Voici une petite question de noob motivé.
Venant du monde de la POO, j'ai démarrer un pgm en C avec un struct
qui contient les données, et des fonctions qui s'appliquent à ce
struct.
Par exemple, dans le header, j'ai ceci :
/* ---------- HEADER ---------- */
typedef struct
(int data1
,int data2
) MonStruct;
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
Mon problème est que les données("data1" et "data2") de "MonStruct"
pourraient être, par inadvertance (ou plutôt feignantise ;-) ),
directement modifiées sans passer par les fonctions.
Est-il possible de pouvoir déclarer les données "data1" et "data2"
dans l'implémentation (le fichier ".c"), de façon à ce que
l'utilisation de MonStruct ne puisse se faire qu'en passant par les
fonctions ?
D'avance merci pour vos avis ou éventuelles remarques.
Non. Et oui.
/* ---------- MonObjet.h ---------- */
#ifndef MonObjet_h
#define MonObjet_h
typedef void* MonObjet;
TSalm writes:Bonjour,
Voici une petite question de noob motivé.
Venant du monde de la POO, j'ai démarrer un pgm en C avec un struct
qui contient les données, et des fonctions qui s'appliquent à ce
struct.
Par exemple, dans le header, j'ai ceci :
/* ---------- HEADER ---------- */
typedef struct
(int data1
,int data2
) MonStruct;
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
Mon problème est que les données("data1" et "data2") de "MonStruct"
pourraient être, par inadvertance (ou plutôt feignantise ;-) ),
directement modifiées sans passer par les fonctions.
Est-il possible de pouvoir déclarer les données "data1" et "data2"
dans l'implémentation (le fichier ".c"), de façon à ce que
l'utilisation de MonStruct ne puisse se faire qu'en passant par les
fonctions ?
D'avance merci pour vos avis ou éventuelles remarques.
Non. Et oui.
/* ---------- MonObjet.h ---------- */
#ifndef MonObjet_h
#define MonObjet_h
typedef void* MonObjet;
Marc writes:"Pascal J. Bourguignon" wrote:typedef void* MonObjet;
extern MonObjet MonObjet_new();
extern void MonObjet_free(MonObjet this);
extern void MonObjet_fait_quelquechose(MonObjet this,int data);
Y a-t-il une raison particulière de passer par un void*? On peut tout à
fait déclarer une struct sans la définir sur place, et ça n'empêche pas
d'utiliser des pointeurs vers elle.
Pour ce que j'en sais, il faut finir par définir ces structures. C'est
ce que l'on veut éviter.
Marc <marc.glisse@gmail.com> writes:
"Pascal J. Bourguignon" wrote:
typedef void* MonObjet;
extern MonObjet MonObjet_new();
extern void MonObjet_free(MonObjet this);
extern void MonObjet_fait_quelquechose(MonObjet this,int data);
Y a-t-il une raison particulière de passer par un void*? On peut tout à
fait déclarer une struct sans la définir sur place, et ça n'empêche pas
d'utiliser des pointeurs vers elle.
Pour ce que j'en sais, il faut finir par définir ces structures. C'est
ce que l'on veut éviter.
Marc writes:"Pascal J. Bourguignon" wrote:typedef void* MonObjet;
extern MonObjet MonObjet_new();
extern void MonObjet_free(MonObjet this);
extern void MonObjet_fait_quelquechose(MonObjet this,int data);
Y a-t-il une raison particulière de passer par un void*? On peut tout à
fait déclarer une struct sans la définir sur place, et ça n'empêche pas
d'utiliser des pointeurs vers elle.
Pour ce que j'en sais, il faut finir par définir ces structures. C'est
ce que l'on veut éviter.
"Pascal J. Bourguignon" wrote:Marc writes:"Pascal J. Bourguignon" wrote:typedef void* MonObjet;
extern MonObjet MonObjet_new();
extern void MonObjet_free(MonObjet this);
extern void MonObjet_fait_quelquechose(MonObjet this,int data);
Y a-t-il une raison particulière de passer par un void*? On peut tout à
fait déclarer une struct sans la définir sur place, et ça n'empêche pas
d'utiliser des pointeurs vers elle.
Pour ce que j'en sais, il faut finir par définir ces structures. C'est
ce que l'on veut éviter.
On la définit dans le fichier .c, qui n'est pas visible par l'utilisateur.
Enfin en tout cas j'ai l'impression que "pimpl" est la réponse à la
question d'origine.
"Pascal J. Bourguignon" wrote:
Marc <marc.glisse@gmail.com> writes:
"Pascal J. Bourguignon" wrote:
typedef void* MonObjet;
extern MonObjet MonObjet_new();
extern void MonObjet_free(MonObjet this);
extern void MonObjet_fait_quelquechose(MonObjet this,int data);
Y a-t-il une raison particulière de passer par un void*? On peut tout à
fait déclarer une struct sans la définir sur place, et ça n'empêche pas
d'utiliser des pointeurs vers elle.
Pour ce que j'en sais, il faut finir par définir ces structures. C'est
ce que l'on veut éviter.
On la définit dans le fichier .c, qui n'est pas visible par l'utilisateur.
Enfin en tout cas j'ai l'impression que "pimpl" est la réponse à la
question d'origine.
"Pascal J. Bourguignon" wrote:Marc writes:"Pascal J. Bourguignon" wrote:typedef void* MonObjet;
extern MonObjet MonObjet_new();
extern void MonObjet_free(MonObjet this);
extern void MonObjet_fait_quelquechose(MonObjet this,int data);
Y a-t-il une raison particulière de passer par un void*? On peut tout à
fait déclarer une struct sans la définir sur place, et ça n'empêche pas
d'utiliser des pointeurs vers elle.
Pour ce que j'en sais, il faut finir par définir ces structures. C'est
ce que l'on veut éviter.
On la définit dans le fichier .c, qui n'est pas visible par l'utilisateur.
Enfin en tout cas j'ai l'impression que "pimpl" est la réponse à la
question d'origine.
Venant du monde de la POO, j'ai démarrer un pgm en C avec un struct qui
contient les données, et des fonctions qui s'appliquent à ce struct.
Par exemple, dans le header, j'ai ceci :
/* ---------- HEADER ---------- */
typedef struct
(int data1
,int data2
) MonStruct;
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
Mon problème est que les données("data1" et "data2") de "MonStruct"
pourraient être, par inadvertance (ou plutôt feignantise ;-) ),
directement modifiées sans passer par les fonctions.
Est-il possible de pouvoir déclarer les données "data1" et "data2" dans
l'implémentation (le fichier ".c"), de façon à ce que l'utilisation de
MonStruct ne puisse se faire qu'en passant par les fonctions ?
Oui, il n'y a que peu de choses à changer à ton code.
/* ---------- HEADER ---------- */
typedef struct MonStruct MonStruct; /* hop */
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
/* ----- implémentation ----- */
struct MonStruct {
int data1;
int data2;
};
/* définitions de fonctions inchangées */
/* -------------------------- */
C'est ce qu'on appelle une structure opaque il me semble. J'imagine que
c'est pour permettre ce genre de choses que le standard spécifie que
« All pointers to structure types shall have the same representation and
alignment requirements as each other. »
Venant du monde de la POO, j'ai démarrer un pgm en C avec un struct qui
contient les données, et des fonctions qui s'appliquent à ce struct.
Par exemple, dans le header, j'ai ceci :
/* ---------- HEADER ---------- */
typedef struct
(int data1
,int data2
) MonStruct;
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
Mon problème est que les données("data1" et "data2") de "MonStruct"
pourraient être, par inadvertance (ou plutôt feignantise ;-) ),
directement modifiées sans passer par les fonctions.
Est-il possible de pouvoir déclarer les données "data1" et "data2" dans
l'implémentation (le fichier ".c"), de façon à ce que l'utilisation de
MonStruct ne puisse se faire qu'en passant par les fonctions ?
Oui, il n'y a que peu de choses à changer à ton code.
/* ---------- HEADER ---------- */
typedef struct MonStruct MonStruct; /* hop */
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
/* ----- implémentation ----- */
struct MonStruct {
int data1;
int data2;
};
/* définitions de fonctions inchangées */
/* -------------------------- */
C'est ce qu'on appelle une structure opaque il me semble. J'imagine que
c'est pour permettre ce genre de choses que le standard spécifie que
« All pointers to structure types shall have the same representation and
alignment requirements as each other. »
Venant du monde de la POO, j'ai démarrer un pgm en C avec un struct qui
contient les données, et des fonctions qui s'appliquent à ce struct.
Par exemple, dans le header, j'ai ceci :
/* ---------- HEADER ---------- */
typedef struct
(int data1
,int data2
) MonStruct;
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
Mon problème est que les données("data1" et "data2") de "MonStruct"
pourraient être, par inadvertance (ou plutôt feignantise ;-) ),
directement modifiées sans passer par les fonctions.
Est-il possible de pouvoir déclarer les données "data1" et "data2" dans
l'implémentation (le fichier ".c"), de façon à ce que l'utilisation de
MonStruct ne puisse se faire qu'en passant par les fonctions ?
Oui, il n'y a que peu de choses à changer à ton code.
/* ---------- HEADER ---------- */
typedef struct MonStruct MonStruct; /* hop */
void MonStruct_create();
void MonStruct_free(MonStruct*);
void MonStruct_fait_quelquechose(MonStruct*,int data);
/* -------------------------- */
/* ----- implémentation ----- */
struct MonStruct {
int data1;
int data2;
};
/* définitions de fonctions inchangées */
/* -------------------------- */
C'est ce qu'on appelle une structure opaque il me semble. J'imagine que
c'est pour permettre ce genre de choses que le standard spécifie que
« All pointers to structure types shall have the same representation and
alignment requirements as each other. »
Autre question, pourquoi utiliser "extern" pour les prototypes de
fonctions ? Est-ce une recommandation pour garder une compatibilité avec
certains compilateurs ?
Autre question, pourquoi utiliser "extern" pour les prototypes de
fonctions ? Est-ce une recommandation pour garder une compatibilité avec
certains compilateurs ?
Autre question, pourquoi utiliser "extern" pour les prototypes de
fonctions ? Est-ce une recommandation pour garder une compatibilité avec
certains compilateurs ?
Il est tout a fait possible de manipuler des struct machin * sans connaitre
struct machin, et ca evite de faire des casts tout moches.
Tu peux parfaitement faire
struct machin;
struct machin *
new_machin(...);
dans ton .h
et n'avoir la definition effective de struct machin que dans le .c...
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Il est tout a fait possible de manipuler des struct machin * sans connaitre
struct machin, et ca evite de faire des casts tout moches.
Tu peux parfaitement faire
struct machin;
struct machin *
new_machin(...);
dans ton .h
et n'avoir la definition effective de struct machin que dans le .c...
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Il est tout a fait possible de manipuler des struct machin * sans connaitre
struct machin, et ca evite de faire des casts tout moches.
Tu peux parfaitement faire
struct machin;
struct machin *
new_machin(...);
dans ton .h
et n'avoir la definition effective de struct machin que dans le .c...
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Comment le compilo fait-il marcher l'arithmétique sur les pointeurs ?
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Comment le compilo fait-il marcher l'arithmétique sur les pointeurs ?
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Comment le compilo fait-il marcher l'arithmétique sur les pointeurs ?
Le 28 janvier 2012, Marc Espie a écrit :Il est tout a fait possible de manipuler des struct machin * sans connaitre
struct machin, et ca evite de faire des casts tout moches.
Tu peux parfaitement faire
struct machin;
struct machin *
new_machin(...);
dans ton .h
et n'avoir la definition effective de struct machin que dans le .c...
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Comment le compilo fait-il marcher l'arithmétique sur les pointeurs ?
Est-ce qu'il met dans l'objet assemblé une sorte de sizeof(machin), à
charge pour le linker de le remplacer par la bonne valeur ?
Le 28 janvier 2012, Marc Espie a écrit :
Il est tout a fait possible de manipuler des struct machin * sans connaitre
struct machin, et ca evite de faire des casts tout moches.
Tu peux parfaitement faire
struct machin;
struct machin *
new_machin(...);
dans ton .h
et n'avoir la definition effective de struct machin que dans le .c...
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Comment le compilo fait-il marcher l'arithmétique sur les pointeurs ?
Est-ce qu'il met dans l'objet assemblé une sorte de sizeof(machin), à
charge pour le linker de le remplacer par la bonne valeur ?
Le 28 janvier 2012, Marc Espie a écrit :Il est tout a fait possible de manipuler des struct machin * sans connaitre
struct machin, et ca evite de faire des casts tout moches.
Tu peux parfaitement faire
struct machin;
struct machin *
new_machin(...);
dans ton .h
et n'avoir la definition effective de struct machin que dans le .c...
Tu as seulement besoin d'avoir la definition d'une structure pour avoir
sa taille, et acceder a ses champs. Pour le reste, genre pour travailler
avec des pointeurs, pas besoin de la definition.
Comment le compilo fait-il marcher l'arithmétique sur les pointeurs ?
Est-ce qu'il met dans l'objet assemblé une sorte de sizeof(machin), à
charge pour le linker de le remplacer par la bonne valeur ?
C'est ce qu'on appelle une structure opaque il me semble.
J'imagine que c'est pour permettre ce genre de choses que le standard
spécifie que « All pointers to structure types shall have the same
representation and alignment requirements as each other. »
C'est ce qu'on appelle une structure opaque il me semble.
J'imagine que c'est pour permettre ce genre de choses que le standard
spécifie que « All pointers to structure types shall have the same
representation and alignment requirements as each other. »
C'est ce qu'on appelle une structure opaque il me semble.
J'imagine que c'est pour permettre ce genre de choses que le standard
spécifie que « All pointers to structure types shall have the same
representation and alignment requirements as each other. »
Je croyais que l'objectif était plutôt de permettre le polymorphisme
(voir la réponse de Samuel pour une extrapolation de l'idée).
En l'occurrence, du point de vue du standard, le "struct MonStruct" du
typedef est un type incomplet, et la déclaration dans «implémentation»
complète le _même_ type ; et évidemment, comme il s'agit du même type,
il est compatible avec lui-même et tous les types pointeur qui en sont
dérivés possèdent les mêmes représentations et contraintes d'alignement.
</HS>
Je croyais que l'objectif était plutôt de permettre le polymorphisme
(voir la réponse de Samuel pour une extrapolation de l'idée).
En l'occurrence, du point de vue du standard, le "struct MonStruct" du
typedef est un type incomplet, et la déclaration dans «implémentation»
complète le _même_ type ; et évidemment, comme il s'agit du même type,
il est compatible avec lui-même et tous les types pointeur qui en sont
dérivés possèdent les mêmes représentations et contraintes d'alignement.
</HS>
Je croyais que l'objectif était plutôt de permettre le polymorphisme
(voir la réponse de Samuel pour une extrapolation de l'idée).
En l'occurrence, du point de vue du standard, le "struct MonStruct" du
typedef est un type incomplet, et la déclaration dans «implémentation»
complète le _même_ type ; et évidemment, comme il s'agit du même type,
il est compatible avec lui-même et tous les types pointeur qui en sont
dérivés possèdent les mêmes représentations et contraintes d'alignement.
</HS>