Je me suis rendu compte il y a peu qu'on pouvait modifier une variable
censée être constante par l'intermédiaire d'un pointeur, voici le code :
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout
à son écoute parce que ça me turlupine ce problème.
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable
censée être constante par l'intermédiaire d'un pointeur, voici le code :
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout
à son écoute parce que ça me turlupine ce problème.
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable
censée être constante par l'intermédiaire d'un pointeur, voici le code :
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout
à son écoute parce que ça me turlupine ce problème.
Bonjour,
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable censée
être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Pour compléter vos tests (j'en fais également beaucoup !), vous pouvez
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout à
son écoute parce que ça me turlupine ce problème.
Le point clé, c'est le cast sauvage const int* -> int*. Remarquez que
Bonjour,
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable censée
être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Pour compléter vos tests (j'en fais également beaucoup !), vous pouvez
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout à
son écoute parce que ça me turlupine ce problème.
Le point clé, c'est le cast sauvage const int* -> int*. Remarquez que
Bonjour,
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable censée
être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Pour compléter vos tests (j'en fais également beaucoup !), vous pouvez
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout à
son écoute parce que ça me turlupine ce problème.
Le point clé, c'est le cast sauvage const int* -> int*. Remarquez que
Je me suis rendu compte il y a peu qu'on pouvait modifier une
variable censée
être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils
montrent quelquechose d'assez surprenant : on a 2 valeurs
différentes pour une même adresse !
Pour compléter vos tests (j'en fais également beaucoup !),
vous pouvez ajouter à la fin:
cout << "*(&a) = " << *((int*)(&a)) << endl;
et au début, essayer:
const volatile int a = 45;
(j'ai mis 45 à la place de votre 0, qui est une valeur "un peu
particulière", mais c'est certainement sans importance)
Résultat du volatile dépend chez moi du compilateur utilisé,
dans un cas (gcc) il suggère clairement au compilateur
d'accéder à la mémoire à chaque accès à a. C'est à mon avis un
bon comportement, le volatile const suggérant une variable en
lecture seule et modifiable "à l'extérieur du programme". Ça
pourrait être le registre d'entrée d'un coupleur E/S.
Alors, si quelqu'un connaît le pourquoi du comment ça se
fait, je suis tout à son écoute parce que ça me turlupine ce
problème.
Le point clé, c'est le cast sauvage const int* -> int*.
Remarquez que la norme autorise à prendre l'adresses d'une
constante (au contraire d'un register par exemple).
A partir de là, vous êtes dans l'indéfini.
Ici, chez moi et chez vous, le compilateur "optimise" en
remplaçant a dans le code certainement par sa valeur
immédiate.
Et même, si a == 0, le compilateur, pour l'affectation x = a,
peut générer un truc du genre CLEAR x si ça existe. Il peut
remplacer x = a*(b + c - d/7) par x = 0. Dernier point: il est
fort possible que les données constantes soient placées dans
une zone mémoire à lecture seule, et que la tentative
d'écriture se solde par une violation d'accès.
Je me suis rendu compte il y a peu qu'on pouvait modifier une
variable censée
être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils
montrent quelquechose d'assez surprenant : on a 2 valeurs
différentes pour une même adresse !
Pour compléter vos tests (j'en fais également beaucoup !),
vous pouvez ajouter à la fin:
cout << "*(&a) = " << *((int*)(&a)) << endl;
et au début, essayer:
const volatile int a = 45;
(j'ai mis 45 à la place de votre 0, qui est une valeur "un peu
particulière", mais c'est certainement sans importance)
Résultat du volatile dépend chez moi du compilateur utilisé,
dans un cas (gcc) il suggère clairement au compilateur
d'accéder à la mémoire à chaque accès à a. C'est à mon avis un
bon comportement, le volatile const suggérant une variable en
lecture seule et modifiable "à l'extérieur du programme". Ça
pourrait être le registre d'entrée d'un coupleur E/S.
Alors, si quelqu'un connaît le pourquoi du comment ça se
fait, je suis tout à son écoute parce que ça me turlupine ce
problème.
Le point clé, c'est le cast sauvage const int* -> int*.
Remarquez que la norme autorise à prendre l'adresses d'une
constante (au contraire d'un register par exemple).
A partir de là, vous êtes dans l'indéfini.
Ici, chez moi et chez vous, le compilateur "optimise" en
remplaçant a dans le code certainement par sa valeur
immédiate.
Et même, si a == 0, le compilateur, pour l'affectation x = a,
peut générer un truc du genre CLEAR x si ça existe. Il peut
remplacer x = a*(b + c - d/7) par x = 0. Dernier point: il est
fort possible que les données constantes soient placées dans
une zone mémoire à lecture seule, et que la tentative
d'écriture se solde par une violation d'accès.
Je me suis rendu compte il y a peu qu'on pouvait modifier une
variable censée
être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils
montrent quelquechose d'assez surprenant : on a 2 valeurs
différentes pour une même adresse !
Pour compléter vos tests (j'en fais également beaucoup !),
vous pouvez ajouter à la fin:
cout << "*(&a) = " << *((int*)(&a)) << endl;
et au début, essayer:
const volatile int a = 45;
(j'ai mis 45 à la place de votre 0, qui est une valeur "un peu
particulière", mais c'est certainement sans importance)
Résultat du volatile dépend chez moi du compilateur utilisé,
dans un cas (gcc) il suggère clairement au compilateur
d'accéder à la mémoire à chaque accès à a. C'est à mon avis un
bon comportement, le volatile const suggérant une variable en
lecture seule et modifiable "à l'extérieur du programme". Ça
pourrait être le registre d'entrée d'un coupleur E/S.
Alors, si quelqu'un connaît le pourquoi du comment ça se
fait, je suis tout à son écoute parce que ça me turlupine ce
problème.
Le point clé, c'est le cast sauvage const int* -> int*.
Remarquez que la norme autorise à prendre l'adresses d'une
constante (au contraire d'un register par exemple).
A partir de là, vous êtes dans l'indéfini.
Ici, chez moi et chez vous, le compilateur "optimise" en
remplaçant a dans le code certainement par sa valeur
immédiate.
Et même, si a == 0, le compilateur, pour l'affectation x = a,
peut générer un truc du genre CLEAR x si ça existe. Il peut
remplacer x = a*(b + c - d/7) par x = 0. Dernier point: il est
fort possible que les données constantes soient placées dans
une zone mémoire à lecture seule, et que la tentative
d'écriture se solde par une violation d'accès.
r = (int *) & a;
r = (int *) & a;
r = (int *) & a;
Bonjour,
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable
censée être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout
à son écoute parce que ça me turlupine ce problème.
Bonjour,
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable
censée être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout
à son écoute parce que ça me turlupine ce problème.
Bonjour,
Je me suis rendu compte il y a peu qu'on pouvait modifier une variable
censée être constante par l'intermédiaire d'un pointeur, voici le code :
const int a = 0;
int *r;
cout << "r = " << r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
r = (int *) & a;
*r = 4;
cout << "r = " << r << endl;
cout << "*r = " << *r << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl << endl;
Bon, les affichages ne sont pas spécialement utiles mais ils montrent
quelquechose d'assez surprenant : on a 2 valeurs différentes pour une même
adresse !
Alors, si quelqu'un connaît le pourquoi du comment ça se fait, je suis tout
à son écoute parce que ça me turlupine ce problème.
C'est en effet l'intention des auteurs de la norme C, au départ.
Selon le compilateur et le système, en revanche... Sur beaucoup
de systèmes, le volatile marche exactement comme on s'y
attendrait, tant qu'il n'y a qu'un seul processeur (ou autre
composant hardware) qui s'y accède. La plupart des compilateurs
que j'ai vu, en revanche, n'insertent pas de barrière de
mémoire, ce qui est nécessaire dès qu'il y a plus d'une entité
hardware qui y accèdent.
Qu'est-ce qu'une barrière de mémoire ? Un truc qui locke certains accès
Remarquez que la norme autorise à prendre l'adresses d'une
constante (au contraire d'un register par exemple).
Comment ça ? Tu peux prendre l'adresse de n'importe quel objet.
Même un objet déclaré régistre. Le mot clé régistre (comme
inline) n'est qu'une suggestion, et comme dit le note dans la
norme : « the hint can be ignored and in most implementations it
will be ignored if the address of the object is take. »
Ben, ISO/IEC 9899:1999 (E), $6.7.1, note 100)
(Mais
que je crois qu'en « most implementations » aujourd'hui, la
suggestion est systèmatiquement ignorée. Sauf peut-être sur une
architecture Intel, extrèmement pauvre en règistres. Et même
là, un bon compilateur saurait mieux faire que le programmeur.)
C'est certain. J'ai déjà plusieurs fois donné *un* exemple dans lequel
A partir de là, vous êtes dans l'indéfini.
Pas du tout. L'indéfini ne s'y introduit que quand on essaie à
modifier l'objet, pas avant.
Oui. Il est effectivement utile de préciser que l'opération
Dans le cas d'un int const, ça m'étonnerait que tu trouves un
compilateur qui ne fait pas cette optimisation. Il faut de toute
façon que le compilateur puisse utiliser la valeur même (et non
la variable) dans des declarations du genre int t[a].
J'en profite pour une question. Sur un compilateur Borland 5.6:
C'est en effet l'intention des auteurs de la norme C, au départ.
Selon le compilateur et le système, en revanche... Sur beaucoup
de systèmes, le volatile marche exactement comme on s'y
attendrait, tant qu'il n'y a qu'un seul processeur (ou autre
composant hardware) qui s'y accède. La plupart des compilateurs
que j'ai vu, en revanche, n'insertent pas de barrière de
mémoire, ce qui est nécessaire dès qu'il y a plus d'une entité
hardware qui y accèdent.
Qu'est-ce qu'une barrière de mémoire ? Un truc qui locke certains accès
Remarquez que la norme autorise à prendre l'adresses d'une
constante (au contraire d'un register par exemple).
Comment ça ? Tu peux prendre l'adresse de n'importe quel objet.
Même un objet déclaré régistre. Le mot clé régistre (comme
inline) n'est qu'une suggestion, et comme dit le note dans la
norme : « the hint can be ignored and in most implementations it
will be ignored if the address of the object is take. »
Ben, ISO/IEC 9899:1999 (E), $6.7.1, note 100)
(Mais
que je crois qu'en « most implementations » aujourd'hui, la
suggestion est systèmatiquement ignorée. Sauf peut-être sur une
architecture Intel, extrèmement pauvre en règistres. Et même
là, un bon compilateur saurait mieux faire que le programmeur.)
C'est certain. J'ai déjà plusieurs fois donné *un* exemple dans lequel
A partir de là, vous êtes dans l'indéfini.
Pas du tout. L'indéfini ne s'y introduit que quand on essaie à
modifier l'objet, pas avant.
Oui. Il est effectivement utile de préciser que l'opération
Dans le cas d'un int const, ça m'étonnerait que tu trouves un
compilateur qui ne fait pas cette optimisation. Il faut de toute
façon que le compilateur puisse utiliser la valeur même (et non
la variable) dans des declarations du genre int t[a].
J'en profite pour une question. Sur un compilateur Borland 5.6:
C'est en effet l'intention des auteurs de la norme C, au départ.
Selon le compilateur et le système, en revanche... Sur beaucoup
de systèmes, le volatile marche exactement comme on s'y
attendrait, tant qu'il n'y a qu'un seul processeur (ou autre
composant hardware) qui s'y accède. La plupart des compilateurs
que j'ai vu, en revanche, n'insertent pas de barrière de
mémoire, ce qui est nécessaire dès qu'il y a plus d'une entité
hardware qui y accèdent.
Qu'est-ce qu'une barrière de mémoire ? Un truc qui locke certains accès
Remarquez que la norme autorise à prendre l'adresses d'une
constante (au contraire d'un register par exemple).
Comment ça ? Tu peux prendre l'adresse de n'importe quel objet.
Même un objet déclaré régistre. Le mot clé régistre (comme
inline) n'est qu'une suggestion, et comme dit le note dans la
norme : « the hint can be ignored and in most implementations it
will be ignored if the address of the object is take. »
Ben, ISO/IEC 9899:1999 (E), $6.7.1, note 100)
(Mais
que je crois qu'en « most implementations » aujourd'hui, la
suggestion est systèmatiquement ignorée. Sauf peut-être sur une
architecture Intel, extrèmement pauvre en règistres. Et même
là, un bon compilateur saurait mieux faire que le programmeur.)
C'est certain. J'ai déjà plusieurs fois donné *un* exemple dans lequel
A partir de là, vous êtes dans l'indéfini.
Pas du tout. L'indéfini ne s'y introduit que quand on essaie à
modifier l'objet, pas avant.
Oui. Il est effectivement utile de préciser que l'opération
Dans le cas d'un int const, ça m'étonnerait que tu trouves un
compilateur qui ne fait pas cette optimisation. Il faut de toute
façon que le compilateur puisse utiliser la valeur même (et non
la variable) dans des declarations du genre int t[a].
J'en profite pour une question. Sur un compilateur Borland 5.6: