Le langage C

a marqué ce sujet comme résolu.

const et volatile s'applique sur ce qui les précède. S'il n'y a rien avant, on inverse et on recommence.

J'ai compris le début mais quand tu dis on recommence, ça veut dire quoi ?

PS: ce n'est pas un warning mais une erreur de compilation que l'on récolte sur le second exemple de code. Qui plus est, a est une constante (potentiellement en ROM, ou chargé directement en paramètre dans les instructions assembleurs), et pas juste une variable non modifiable.

Avec les bonnes options de compilations on obtient une erreur. Je viens de tester pour être sûr : avec -Wall ou -pedantic, on obtient bien un warning et j'obtiens l'erreur en rajoutant -Werror (ce qui est bien normal). Mais ce que tu dis là m'intéresses, si elle est potentiellement chargée en ROM, on va droit à la catastrophe avec le code que j'ai donné. Alors ça m'interpelle que j'obtiens seulement un warning.

+0 -0

C'est quoi ton compilo ? Mon gcc 4.8.2 me donne (sans option donc):

1
2
3
4
g++     const.cpp   -o const
const.cpp: In function `int main()`:
const.cpp:4:15: erreur: invalid conversion from `const int*` to `int*` [-fpermissive]
     int *p = &a;            

Et même chose pour clang (3.7.0 (trunk 234879)):

1
2
3
clang++     const.cpp   -o const
const.cpp:4:10: error: cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'
    int *p = &a;

Mets à jour ton compilo. Et pour les optims, cf le TR18015

Ah ? Je percute, en lisant maintenant le nom du topic, tu compiles en C, non ? Ceci dit, j'ai toujours une erreur par gcc et par clang (sans les ++)

EDIT: pour le "et on recommence", c'est comme dans les règles: "R1 j'ai toujours raison; R2. dans l'éventualité où j'ai tord, se référer à R1". Ici: "R1, const s'applique à ce qui le précède; R2, dans l'éventualité où rien ne le précède, on l'échange avec ce qui le suit et on applique R1"

J'ai la même version de gcc, mais j'utilise gcc et pas g++ puisqu'on parle de langage C.

+0 -0

Faudra que je teste sous Linux pour voir mais en tout cas avec mingw :

1
2
3
4
gcc new.c
new.c: In function `main`:
new.c:6:13: warning: initialization discards `const` qualifier from pointer target type [enabled by default]
    int *p = &a;
+0 -0

Pourquoi je ne suis pas entièrement surpris. Le gnumake qui accompagne mingw est déjà une cata (il ne vient pas avec les règles implicites qui permet de taper make const et de le laisser appeler le bon compilateur en fonction de s'il trouve const.c, const.cpp, etc. Mais là, c'est tout de même étrange.

J'ai testé sous Arch avec gcc 5.2 :

  • gcc new.c -> warning
  • g++ new.c -> warning
  • gcc new.cpp -> erreur
  • g++ new.cpp -> erreur

Alors là tout me laisse penser qu'on obtient une erreur en C++ mais qu'un warning en C. Tu en penses quoi ?

+1 -0

J'en pense que c'est chelou au possible – et rassurant pour mingw. gcc ne devrait pas regarder le nom du fichier et pourtant …

Mon gcc 4.8.2, quand je tape g++ const.c me donne tout de même un warning et pas une erreur.

Pour le fait que C soit plus laxiste au regard de const, cela va cependant dans le sens de mes souvenirs sur le sujet comme quoi il y avait de subtiles différences – j'ai juste totalement paumé le lien que j'avais sur le sujet.
Après une recherche sur SO & cie, je lis qu'en C, une variable déclarée const peut-être modifiée par ailleurs, alors qu'en C++, c'est une vrai constante – dans le cas de ton code. D'où que c'est ROMable en C++, mais pas en C, et que l'on a donc juste un warning. Diantre. On en apprend tous les jours.

J'en pense que c'est chelou au possible – et rassurant pour mingw. gcc ne devrait pas regarder le nom du fichier et pourtant …

Mon gcc 4.8.2, quand je tape g++ const.c me donne tout de même un warning et pas une erreur.

Ouf, je commençais à avoir peur.

Pour le fait que C soit plus laxiste au regard de const, cela va cependant dans le sens de mes souvenirs sur le sujet comme quoi il y avait de subtiles différences – j'ai juste totalement paumé le lien que j'avais sur le sujet.
Après une recherche sur SO & cie, je lis qu'en C, une variable déclarée const peut-être modifiée par ailleurs, alors qu'en C++, c'est une vrai constante – dans le cas de ton code. D'où que c'est ROMable en C++, mais pas en C, et que l'on a donc juste un warning. Diantre. On en apprend tous les jours.

Donc finalement en C++, c'est bon le compilateur nous indique l'erreur (de toute manière, j'imagine que dans ces cas là, les devs utilisent auto) et en C, on nous laisse faire. J'aurais plutôt pensé à la même permissivité. Il est vivement temps que j'apprenne vraiment le C++.

EDIT : si tu retrouves le lien sur le sujet, j'aimerais bien que tu me le passes.

+0 -0

Pour le fait que C soit plus laxiste au regard de const, cela va cependant dans le sens de mes souvenirs sur le sujet comme quoi il y avait de subtiles différences – j'ai juste totalement paumé le lien que j'avais sur le sujet.
Après une recherche sur SO & cie, je lis qu'en C, une variable déclarée const peut-être modifiée par ailleurs, alors qu'en C++, c'est une vrai constante – dans le cas de ton code. D'où que c'est ROMable en C++, mais pas en C, et que l'on a donc juste un warning. Diantre. On en apprend tous les jours.

lmghs

En C, la compilation n'avortera que si un objet est modifié via une expression dont le type est qualifié de constant. Par exemple, dans les cas suivant.

1
2
3
4
5
int const a = 10;
int const *p = &a;

a = 20; /* faux */
*p = 42: /* faux aussi */

Pour le reste, modifier un objet dont le type est qualifié de constant à l'aide d'une expression dont le type n'est pas qualifié de constant engendre un comportement indéfini. C'est pour cela que le compilateur n'émet qu'un avertissement.

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

ISO/IEC 9899:201x (doc. N1570), § 6.7.3, al. 6, p. 122

La norme précise également qu'un objet qualifié de constant (mais pas de volatile) peut être placé dans une région en lecture seule (d'où le comportement indéfini dans le cas précédent).

The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used.

ISO/IEC 9899:201x (doc. N1570), § 6.7.3, note 132, p. 121

+2 -0

Bonjour à tous,

Les dernières suggestions et corrections viennent d'être appliquées (oui, même en ce qui concerne les apostrophes). Aussi, la bêta va à présent être clôturée. Merci à tous pour vos encouragements, corrections, suggestions et critiques. ;)

+0 -0

Bonjour à tous,

Le cours vient d’être mis à jour afin de se baser sur la norme C11. :)
Au menu :

  • Introduction plus brève ;
  • Choix de MSys2 au lieu de MinGW32 pour les utilisateurs de Windows ;
  • Adaptation de la liste des types et de leurs limites ;
  • Mise à jour de la liste des mots-clés ;
  • Modification de la liste des indicateurs de conversions pour printf() et scanf() ;
  • Meilleure explication de la construction else if ;
  • Présentation de l’initialisation sélective pour les tableaux et les structures ;
  • Exposé des tableaux et structures littérales ;
  • Utilisation des opérateurs _Alignof et _Alignas ;
  • Correction de l’explication relative à l’origine de l’indice zéro des tableaux ;
  • Emploie de la fonction snprintf() au lieu de sprintf() ;
  • Ajout d’une section discutant des tableaux de longueur variable ;
  • Scission du chapitre sur les encodages en deux chapitres : l’un sur la localisation et l’internationalisation et l’autre sur les encodages et caractères larges ;
  • Présentation des structures et union anonymes ;
  • Ajout d’une section concernant les macrofonctions à nombre variable d’arguments ;
  • Nouveau chapitre relatif aux sélections génériques ;
  • Changements des exemples de codes, notamment pour profiter des définitions de variable en milieu de bloc ;
  • Utilisation de schéma en ASCII art (parce que c’est joli) ;
  • Ajout d’une section « en résumé » à la fin de chaque chapitre (ce n’était le cas que pour la partie 3).

Le chapitre « Tables de correspondance et caractères larges » est toujours en cours d’écriture et sera ou non inclus dans la demande de validation future suivant son avancée. ^^"

En attendant, bonne lecture. ;)

+1 -0
Ce sujet est verrouillé.