Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Empêcher l'accès aux données d'un struct

36 réponses
Avatar
TSalm
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.
-TSalm

10 réponses

1 2 3 4
Avatar
Manuel Pégourié-Gonnard
Antoine Leca scripsit :

Manuel Pégourié-Gonnard écrit :
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.



Du côté implémentation, oui on est d'accord. Mais côté utilisateur, le
compilo voit :

struct foo; /* via #include "interface.h" */

/* plus loin */
struct foo *bar;

Et là il me semble qu'il a besoin de connaître la (taille de la)
réprésentation et les contraintes d'alignement des struct foo *,
histoire de pouvoir allouer de la place pour bar. Donc il faut qu'il
connaisse ces choses pour un pointeur sur un type structure même
incomplet.

Du coup il me semble que si la norme ne précisait pas que tous les
pointeurs vers des structures ont la même représentation et les mêmes
contraintes d'alignement, le fragment de code ci-dessus ne serait pas
compilable (ou pas de façon portable en tout cas).

Ou alors je suis à côté de la plaque ?

--
Manuel Pégourié-Gonnard - http://people.math.jussieu.fr/~mpg/
Avatar
Antoine Leca
Manuel Pégourié-Gonnard écrivit :
Manuel Pégourié-Gonnard écrit :
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. »




Mais côté utilisateur, le compilo voit :

struct foo; /* via #include "interface.h" */

/* plus loin */
struct foo *bar;

Et là il me semble qu'il a besoin de connaître la (taille de la)
réprésentation et les contraintes d'alignement des struct foo *,
histoire de pouvoir allouer de la place pour bar.



Le fait qu'il ait besoin de les connaître n'oblige pas nécessairement à
ce que ces contraintes soient systématiquement identiques à celles des
autres cas de figures de pointeurs vers structures. ÀMHA.


Donc il faut qu'il connaisse ces choses pour un pointeur sur un
type structure même incomplet.



Si on suppose que la clause du standard n'existait pas, et si l'on
considère le cas hypothétique d'une architecture segmentée avec des gros
et des petits objets (et des pointeurs vers gros plus efficaces que les
pointeurs vers petits), le compilateur aurait à ce niveau-là le choix
entre :
1) ceinture et bretelles, je suppose que struct foo est un petit objet
et je décide que bar sera donc un pointeur vers petit donc inefficace
2) optimateur fou, je suppose que struct foo est un gros objet etc.
Et si dans la pratique il s'avère que l'objet est en fait petit, il faut
alors passer par une double indirection ou autres horreurs...

En général, à ce niveau-là dans les compilateurs tu as une option qui
permet de forcer un choix ou l'autre, voire une syntaxe complémentaire

struct foo __attribute(petit)* bar;
struct foo __attribute(gros) * baz;

Voire, en extrapolant juste un tout petit peu

struct foo __far* bar;
struct foo __based(__segment(QUIRK))* baz;

:-)

Du coup il me semble que si la norme ne précisait pas que tous les
pointeurs vers des structures ont la même représentation et les mêmes
contraintes d'alignement, le fragment de code ci-dessus ne serait pas
compilable (ou pas de façon portable en tout cas).



Sauf erreur de ma part, dans le cas (1) il n'y a pas de souci, seulement
une perte de possibilité d'optimisations vis-à-vis du cas (2); mais tu
peux utiliser le cas (2) dans d'autres cas de figures (quand la
structure est définie, ce qui est quand même le plus courant) ce qui
serait alors non conforme à la norme.

Dans le cas (2) c'est effectivement plus compliqué pour satisfaire la
totalité des règles de la norme (en particulier le fait que les adresses
sont invariantes, ce qui ne se marie pas bien avec les mécanismes de
double tampons...) Désolé de ne pas pouvoir détailler...


Antoine
Avatar
Samuel DEVULDER
Le 01/02/2012 12:53, Manuel Pégourié-Gonnard a écrit :

Du côté implémentation, oui on est d'accord. Mais côté utilisateur, le
compilo voit :

struct foo; /* via #include "interface.h" */

/* plus loin */
struct foo *bar;

Et là il me semble qu'il a besoin de connaître la (taille de la)
réprésentation et les contraintes d'alignement des struct foo *,
histoire de pouvoir allouer de la place pour bar.



Pourquoi? Si je me mets à la place du CPU: un pointeur est un pointeur,
une adresse mémoire et, généralement parlant (on ignore les far/near
et autres "paged"), toutes les adresses ont la même taille. Du point de
vu du processeur, un pointeur sur X ou sur Y c'est toujours un
pointeur. On a uniquement besoin de connaitre X ou Y si:

- on accède aux champs (évidemment): bar->champ

- on fait de l’arithmétique avec les pointeurs: ++bar (pour savoir de
combien d'octets avancer).

- on accède à autre chose que *bar ou bar[0]: en effet
bar[i] = *(bar + i*sizeof(struct foo)) et sizeof(struct foo)
n'est pas connu.

Donc en gros tant qu'on utilise bar comme l'adresse d'un élément
struct foo sans changer sa valeur, alors on ne se préoccupe pas
de la taille ou de la structure de la zone mémoire pointée et alors
tout doit marcher correctement sans avoir besoin de plus d'information.

sam.
Avatar
Antoine Leca
Samuel DEVULDER écrivit :
struct foo; /* via #include "interface.h" */

/* plus loin */
struct foo *bar;

Et là il me semble qu'il a besoin de connaître la (taille de la)
réprésentation et les contraintes d'alignement des struct foo *,
histoire de pouvoir allouer de la place pour bar.



Pourquoi? Si je me mets à la place du CPU: un pointeur est un pointeur,
une adresse mémoire et, généralement parlant (on ignore les far/near
et autres "paged"), toutes les adresses ont la même taille.



Le problème ici est précisemment celui des far/near et autres "paged",
ou encore celui des architectures où il existe plusieurs tailles de
pointeurs.


Du point de vu du processeur, un pointeur sur X ou sur Y c'est
toujours un pointeur. On a uniquement besoin de connaitre X ou Y si:


[couic]
- on accède aux champs (évidemment): bar->champ

- on fait de l’arithmétique avec les pointeurs: ++bar (pour savoir de
combien d'octets avancer).

- on accède à autre chose que *bar ou bar[0]: en effet
bar[i] = *(bar + i*sizeof(struct foo)) et sizeof(struct foo)
n'est pas connu.



- on transtype le pointeur en pointeur vers autre chose


Donc en gros tant qu'on utilise bar comme l'adresse d'un élément
struct foo sans changer sa valeur, alors on ne se préoccupe pas
de la taille ou de la structure de la zone mémoire pointée et alors
tout doit marcher correctement sans avoir besoin de plus d'information.



Cela me paraît une tautologie, donc je n'ai pas compris ton argument.

Les pointeurs ont parfois d'autres utilisations que celles de
représenter un objet unique, voire au delà des objets au sein d'un même
tableau. En particulier, on manipule parfois un pointeur «générique» et
on le passe à un sous-programme qui le traitera comme un pointeur vers
un type déterminé, qui peut dépendre du sous-programme. La norme ANSI a
créé pour cela le type void* (au lieu de char* à l'origine), mais ce
n'est pas forcément le plus efficace, le fait d'utiliser un type
passe-partout peut aussi cacher des problèmes de types (mélange de choux
et de carottes).


Antoine
Avatar
espie
In article <jgdj75$jau$,
Antoine Leca wrote:
Samuel DEVULDER écrivit :
struct foo; /* via #include "interface.h" */

/* plus loin */
struct foo *bar;

Et là il me semble qu'il a besoin de connaître la (taille de la)
réprésentation et les contraintes d'alignement des struct foo *,
histoire de pouvoir allouer de la place pour bar.



Pourquoi? Si je me mets à la place du CPU: un pointeur est un pointeur,
une adresse mémoire et, généralement parlant (on ignore les far/near
et autres "paged"), toutes les adresses ont la même taille.



Le problème ici est précisemment celui des far/near et autres "paged",
ou encore celui des architectures où il existe plusieurs tailles de
pointeurs.



Oui, mais justement, ca n'est plus du C standard.
Une des avancees majeures du langage, ca a ete justement de simplifier
l'immonde fatras anterieur des processeurs avec 15 tailles de mot et de
pointeurs differents, et de dire, voila t'as des char, et tout "marche"
avec des char.

Une concession pour les pointeurs de fonction, un accident historique pour
les archi pas tout a fait assez puissantes pour faire du C (far/near) et
qui avaient envie de faire semblant, et zou, emballe c'est pese.


Le reste on oublie, et heureusement.

Apres, tu peux parler de dialectes de C qui sortent completement de la
norme, mais ca devient tres tres anecdotique, et de moins en moins utile
aujourd'hui...
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

Pourquoi? Si je me mets à la place du CPU: un pointeur est un pointeur,
une adresse mémoire et, généralement parlant (on ignore les far/near
et autres "paged"), toutes les adresses ont la même taille.



Non. Sur une machine adressable par mot où l'implémentation fait le choix
d'avoir un char qui correspond à une sous-unité du mot, un pointeur vers un
char ou vers un short peut avoir un format différent des autres pointeurs.

La norme demande donc pour les structs d'utiliser soit des pointeurs
normaux et d'avoir des structs alignées au moins sur les mots (et donc une
struct ne contenant qu'un char aura une taille plus grande que un), soit
des pointeurs plus grands (et donc les pointeurs vers des structs devant
être bien alignées pour d'autres raisons prendront plus de place que
nécessaire).

La seule implémentation que je connais pour une machine adressable par mot
utilisant des parties de mots comme char utilise des pointeurs de même
taille pour char* et int* (car utiliser une taille plus petite ne
permettrait pas d'adresser tout l'espace mémoire), mais le format interne
est différent. Et les pointeurs vers des structs utilisent le même format
que int* (dont une struct avec un seul char a une taille de 4).

(Ce genre d'architecture n'est d'un intérêt qu'annectotique de nos jours;
les seules machines adressables par mots ne sont pas utilisées pour
manipuler des caractères et les implémentations du C pour ces machines font
le choix plus simple char=short=int).

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Samuel DEVULDER
Le 02/02/2012 18:41, Jean-Marc Bourguet a écrit :

Non. Sur une machine adressable par mot où l'implémentation fait le choix
d'avoir un char qui correspond à une sous-unité du mot, un pointeur vers un
char ou vers un short peut avoir un format différent des autres pointeurs.



Que le format soit différents, ok. Mais même taille est identique, non?
sinon comment tu passes vers/depuis un void* sans perdre des bits au
passage?

La norme demande donc pour les structs d'utiliser soit des pointeurs
normaux et d'avoir des structs alignées au moins sur les mots (et donc une
struct ne contenant qu'un char aura une taille plus grande que un), soit



Que les struct aient des tailles différentes suivant le padding, c'est
entendu. Mais ton pointeur sur la struct a une taille standard, non?

des pointeurs plus grands (et donc les pointeurs vers des structs devant
être bien alignées pour d'autres raisons prendront plus de place que
nécessaire).



Admettons qu'il existe des pointeurs plus gros que les standard pour
ces structures spéciales. Alors comment fais tu pour utiliser les
fonctions standard (memset/memcpy/...) qui ne connaissent que les
pointeurs "plus petits" ? On perd de l'info quelque part.

J'avoue ne pas trop suivre ou imaginer la situation. D'ailleurs je n'ai
jamais rencontré ce cas. As tu un nom de machine et de compilo C qui
aient des pointeurs parfois "plus gros" que les autres. Cela
m'intrigue.

Par contre, j'ai vu l'inverse: les pointeurs C est plus gros que
le registre d'adresse du cpu pour tenir compte de modes d'adressage
spéciaux (mémoire paginée par exemple). Et dans ce cas, tous les
pointeurs sont plus gros, et il n'y a pas de problème pour appeler
les bibliothèques standard. Tout est (a peu près) homogène dans l'ABI.

La seule implémentation que je connais pour une machine adressable par mot
utilisant des parties de mots comme char utilise des pointeurs de même
taille pour char* et int* (car utiliser une taille plus petite ne
permettrait pas d'adresser tout l'espace mémoire), mais le format interne
est différent. Et les pointeurs vers des structs utilisent le même format
que int* (dont une struct avec un seul char a une taille de 4).



Oui donc, tous les pointeurs ont au final la même taille (celle d'un
int*) si je comprends bien. C'est ce que je disais au début: Pour
allouer de la place pour "bar" dans:

struct foo *bar;

le compilo n'a pas besoin de connaitre le détail de l'intérieur de foo.
Le modèle est homogène et tous les pointeurs font la même taille. Par
contre je peux comprendre que l'organisation des bits d'un char* soit
différent de ceux d'un int*.. mais le sizeof() lui est identique et
c'est bien de cela dont il est question ici.

(Ce genre d'architecture n'est d'un intérêt qu'annectotique de nos jours;
les seules machines adressables par mots ne sont pas utilisées pour
manipuler des caractères et les implémentations du C pour ces machines font
le choix plus simple char=short=int).



Quitte a perdre un peu de place en mémoire en effet. Mais bon, de toute
façon il y a les wchar à présent.. et donc avoir un char sur 16 ou
32bits n'est plus aussi choquant à une époque où on manipule de
l'UTF-32.

sam.
Avatar
Samuel DEVULDER
Le 02/02/2012 12:31, Marc Espie a écrit :

Apres, tu peux parler de dialectes de C qui sortent completement de la
norme, mais ca devient tres tres anecdotique, et de moins en moins utile
aujourd'hui...



Oui en effet. Pour autant que j'en ai pu en juger sur des archi
bizzares, les compilos s'arrangent pour que le sizeof(pointeur)
soit constant et que tous les pointeurs "void*" soient capables de
pointer sur tout ce qu'on veut, quitte à alourdir le code ASM généré
pour décoder les "trucs en plus" non supportés nativement par
les registres d’adresse natifs du CPU (changement de page mémoire
par exemple). De toute façon c'est nécessaire pour avoir accès aux
bibliothèques standard qui ont besoin d'un void* (memset).

Après, si l'on a besoin de trucs très spécifiques (par exemple
avoir un type "pointeur" capable de n'adresser que la pile
présente dans les 256 premiers octets de mémoire), alors je crois
qu'on a quitté le C abstrait pour entrer de plein pied dans l'ASM
bien concret. L'idéal à ce niveau et de faire en ASM les choses
spécifiques au matériel et ne pas polluer le C avec des choses qui
ne sont pas de son ressort. Ainsi, pour le coup j'aurais tendance à
dire que le pointeur 8bits du du début de paragraphe n'est pas un
pointeur C mais plus un accès direct au registre de pile du processeur.
D'ailleurs si cela avait été un pointeur, qu'aurait donné un appel
à memset() avec lui en paramètre? (un beau plantage à mon avis)

Finalement, à chaque niveau d'abstraction correspond son langage type.
Si on est proche de l'architecture matérielle, on a l'assembleur où il
faut tout gérer; si on veut s'abstraire du matériel via un OS, alors
on fait du C (ansi?). On gère moins de chose bas niveau et les pointeurs
sont tous compatibles les uns avec les autres à cause des bibliothèques
standards mais il faut encore s'occuper de l'allocation/libération de
mémoire par exemple; enfin si on veut s'abstraire encore plus de l'OS
il y a les langages où ce dernier est complètement masqué, où la notion
de pointeur a complètement disparue et où l'on ne se préoccupe plus
delibérer les resources à la main par exemple.

sam (my 2cents).
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

Le 02/02/2012 18:41, Jean-Marc Bourguet a écrit :

Non. Sur une machine adressable par mot où l'implémentation fait le choix
d'avoir un char qui correspond à une sous-unité du mot, un pointeur vers un
char ou vers un short peut avoir un format différent des autres pointeurs.



Que le format soit différents, ok. Mais même taille est identique, non?
sinon comment tu passes vers/depuis un void* sans perdre des bits au
passage?



Tu pourrais avoir des tailles différentes. Un void* devrait simplement
avoir une taille suffisante pour le plus grand format (vraisemblablement
sans même indiquer duquel il s'agit) ou les cast de et vers void faire de
la transformation de données.

La norme demande donc pour les structs d'utiliser soit des pointeurs
normaux et d'avoir des structs alignées au moins sur les mots (et donc une
struct ne contenant qu'un char aura une taille plus grande que un), soit



Que les struct aient des tailles différentes suivant le padding, c'est
entendu. Mais ton pointeur sur la struct a une taille standard, non?



struct s { char c; }

Soit tu as sizeof(struct s) == 1, et tu utilises le même format que char*
pour toutes les structs, soit tu ajoutes du padding

des pointeurs plus grands (et donc les pointeurs vers des structs devant
être bien alignées pour d'autres raisons prendront plus de place que
nécessaire).



Admettons qu'il existe des pointeurs plus gros que les standard pour
ces structures spéciales. Alors comment fais tu pour utiliser les
fonctions standard (memset/memcpy/...) qui ne connaissent que les
pointeurs "plus petits" ? On perd de l'info quelque part.



C'est plutôt l'inverse, les char* (et les void*) plus grand que les struct*.

J'avoue ne pas trop suivre ou imaginer la situation. D'ailleurs je n'ai
jamais rencontré ce cas. As tu un nom de machine et de compilo C qui
aient des pointeurs parfois "plus gros" que les autres. Cela m'intrigue.



L'implémentation logique pour un PDP-10 sans mémoire étendue serait d'avoir
un char de 9 bit, un short de 18 bit, un int et un long de 36 bits. Un
void*, char* et short* sur 36 bits, les autres pointeurs (sauf peut-être
les enums, je ne sais plus les contraintes sur eux) sur 18 bits.

Comme je l'ai écris, l'implémentation que je connais supporte la mémoire
étendue et a donc tous les pointeurs sur 36 bits (et elle permet d'utiliser
des char sur 8 ou 7 bits; ce qui n'est pas conforme mais permet une
meilleure interopérabilité avec le reste du système).

Le GE-635 (une des premières machines sur lesquelles C a été porté) a une
organisation mémoire proche de celle du PDP-10 (c'est aussi une machine
adressant des mots de 36 bits, avec des adresses sur 18 bits, ce qui est
une organisation qui remonte au moins à l'IBM 701 vers 1950). Ça ne
m'étonnerait pas qu'elle ait utilisé eu ces tailles, mais j'ai trouvé peu
d'info dessus (http://www.lysator.liu.se/c/bwk-tutor.html indique que int
était sur 36 bits et char sur 9 -- à cette époque short et long n'existait
pas encore -- mais je n'ai rien vu sur la taille des pointeurs)

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Samuel DEVULDER
Le 04/02/2012 22:35, Jean-Marc Bourguet a écrit :

Tu pourrais avoir des tailles différentes. Un void* devrait simplement
avoir une taille suffisante pour le plus grand format (vraisemblablement
sans même indiquer duquel il s'agit) ou les cast de et vers void faire de
la transformation de données.



ok pour un "void*" suffisamment grand pour tout contenir, ca parait
plus logique.

struct s { char c; }

Soit tu as sizeof(struct s) == 1, et tu utilises le même format que char*
pour toutes les structs, soit tu ajoutes du padding



Donc sur ces machines, suivant qu'on pointe sur un simple caractère ou
sur quelque chose de plus structuré, on a pas les mêmes pointeur si je
comprends bien ce que tu me dis. Pourquoi ne pas avoir choisi un
architecture homogène avec des pointeurs tous identiques ? C'est lié à
un problème de ressource mémoire? En tout cas il semble que toutes
les "struct*" ont la même taille (c'etait le point de départ de la
discussion).

Admettons qu'il existe des pointeurs plus gros que les standard pour
ces structures spéciales. Alors comment fais tu pour utiliser les
fonctions standard (memset/memcpy/...) qui ne connaissent que les
pointeurs "plus petits" ? On perd de l'info quelque part.



C'est plutôt l'inverse, les char* (et les void*) plus grand que les struct*.



struct s { char c; };
struct t { struct s; } toto;

struct t *pt = &toto;
struct s *ps = &pt->s;
char *pc = &ps->c;

Donc:
sizeof(pt) == sizeof(ps) car ce sont deux pointeurs sur struct, mais
sizeof(ps) != sizeof(pc).

Comment fait le compilo pour générer un appel à memset(ps, 0, 1) et à
memset(pc, 0, 1)?

Y a-t-il deux versions de memset, une pour les "char*" et l'autre pour
les "struct*" ? Non ca ne semble complexe il faudrait faire ca pour
toutes les fonctions acceptant un void*. Je suppose qu'en réalité
le compilo va caster le struct *ps en void* et empiler un pointeur
plus grand qu'à l'origine.

J'avoue ne pas trop suivre ou imaginer la situation.





C'est plus clair à présent.. mais je le pose une question sur le retour
de fonction du type void* et le cast en pointeur "plus petit". Par
exemple si on a:

void *foo(void *ptr) {
char *s = ptr;
*s++ = '';
return s;
}

et qu'on appelle

pc = foo(pc);

Tout se passe bien... pc est un "gros" pointeur, on ne perd pas de bits
par rapport à void*. Mais si on fait:

ps = foo(ps);

on va perdre des bits et la valeur retournée ne sera pas correctement
placée dans ps.

Hum... en fait je pense que cet exemple est typiquement foireux à cause
du padding. En effet ps+1 est fondamentalement distinct de pc+1 et de
plus en fonction de la position du bourrage, cette fonction peut même
ne pas avoir vraiment modifié ps->c. Ok c'est n'importe quoi ce code.
Cette fonction aurait du être écrite:

void *foo(void *ptr, int len) {
char *s = ptr;
while(len--) *s++ = '';
return s;
}
pc = foo(pc, sizeof(*pc));

Et là, avec ou sans padding, la valeur retournée pointe bel et bien sur
ps+1.

Ok tout a l'air cohérent à présent. Je vais pouvoir me coucher moins
bête ;-)

jamais rencontré ce cas. As tu un nom de machine et de compilo C qui
aient des pointeurs parfois "plus gros" que les autres. Cela m'intrigue.



L'implémentation logique pour un PDP-10 sans mémoire étendue serait d'avoir
un char de 9 bit, un short de 18 bit, un int et un long de 36 bits. Un
void*, char* et short* sur 36 bits, les autres pointeurs (sauf peut-être
les enums, je ne sais plus les contraintes sur eux) sur 18 bits.



Ok ca conforte l'hypothèse d'économie de mémoire alors. Du point de
vu performances, on a donc intérêt à n'utiliser que des "struct*"
dans ses progs plutôt que des void* et éviter ainsi les conversions
implicites entre petits et gros pointeurs.

Le GE-635 (une des premières machines sur lesquelles C a été porté) a une
organisation mémoire proche de celle du PDP-10 (c'est aussi une machine
adressant des mots de 36 bits, avec des adresses sur 18 bits, ce qui est
une organisation qui remonte au moins à l'IBM 701 vers 1950). Ça ne



1950? Oui donc c'est vraiment de l'archéo-programmation ce problème de
modèle mémoire distinct entre char* et struct*. Sur les machines
d'après 1980 cette problématique ne devrait plus être très fréquente.

m'étonnerait pas qu'elle ait utilisé eu ces tailles, mais j'ai trouvé peu
d'info dessus (http://www.lysator.liu.se/c/bwk-tutor.html indique que int
était sur 36 bits et char sur 9 -- à cette époque short et long n'existait
pas encore -- mais je n'ai rien vu sur la taille des pointeurs)



a+

sam.
1 2 3 4