Partage
  • Partager sur Facebook
  • Partager sur Twitter

C++ ligne avec const char*, char_traits

C++

19 décembre 2018 à 16:34:22

Bonsoir 

je suis en train de chercher à comprendre les char_traits avec l'exemple de cppreference:

https://en.cppreference.com/w/cpp/string/char_traits

Pendant que je fais des tests sur ce code, je faisais un test simple sur des char :

const char *s1=new char(41);

me donne la valeur voulue ")" à l'affichage , ce qui est tout à fait normale conformément à la correspondance ASCII

http://www.asciitable.com/

Par contre, d'une manière que je voudrais pouvoir expliquer quand je fais :

const char *s1=new char('41');

j'obtiens 1 à l'exécution. 

Quelqu'un peut-il m'expliquer comment faire pour le comprendre ?

Merci

  • Partager sur Facebook
  • Partager sur Twitter
19 décembre 2018 à 16:45:11

Je suis étonné que tu ne te sois pas pris un warning. Entre côtes, on attend qu'un caractère ASCII, donc '41' qui en fait deux, je pensais que ça balancerai un warning.

Non, visiblement, il ne garde que le dernier (vérifié en debug) . C'est comme si tu avais rentré '1' le 4 est ignoré.

  • Partager sur Facebook
  • Partager sur Twitter

Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

19 décembre 2018 à 16:45:47

Salut,

Ces liens te fourniront des éléments de réponse sur la notion de "Multicharacter literals" :

https://en.cppreference.com/w/c/language/character_constant

https://en.cppreference.com/w/cpp/language/character_literal

 ..................................................................................

"Multicharacter literals were inherited by C from the B programming language. Although not specified by the C or C++ standard, compilers implement multicharacter literals as specified in B: the values of each char in the literal initialize successive bytes of the resulting integer, in big-endian zero-padded right-adjusted order, e.g. the value of '\1' is 0x00000001 and the value of '\1\2\3\4' is 0x01020304."

 ..................................................................................

Donc si je comprends bien, '41' = 0x0401, et comme tu le mets dans un "char", le "cast" te fais perdre le "0x04"...d'où le 1.

  ..................................................................................

EDIT : Erratum...Raté...l'explication qui est cité "correspond aux représentations binaires (donc avec \), ce qui n'est pas le cas ici."

-
Edité par CeBiM 20 décembre 2018 à 15:45:52

  • Partager sur Facebook
  • Partager sur Twitter
Les seules questions bêtes sont celles qui ne sont pas posées. Mieux vaut paraître bête une fois que de le rester à vie."Vis comme si tu devais mourir demain. Apprends comme si tu devais vivre toujours."
19 décembre 2018 à 16:48:49

Tu es dans le cas 6 décrit par la doc des littéraux de type caractère

'41' est un Multicharacter literal, ça ne veut rien dire et le résultat est un entier défini selon l'implémentation dans le compilateur, donc il n'y a rien à comprendre

  • Partager sur Facebook
  • Partager sur Twitter
Dream on, Dream on, Dream until your dream comes true
19 décembre 2018 à 16:50:12

Tu manipules (confonds peut-être?) nombre, caractère et chaine de caractères

41: nombre

'41': n'existe pas en C, ni en C++ (EDIT: WTF?! Ca compile ?!)

"41": chaine de caractères C 0-terminée -- je simplifie à mort

new char(): alloue un caractère

new char[]: alloue un tableau de caractères

PS: l'ASCII, on s'en fout, dans un code C ou C++ (ou Pascal, Ada, Python...) tout code ASCII qui apparait en dur est une obfuscation qui ne sert qu'à deux choses: montrer que l'on n'a pas compris que c'est compliqué pour rien, ou pour faire exprès de rendre un code compliqué afin de participer à l'IOCCC (https://www.ioccc.org/). Quand je suivais des cours il y a 25-30 ans, je croyais que cela servait à quelque chose dans un code, maintenant je sais que je ne faisais que reproduire des pratiques ancestrales figées qui ne servaient à rien (https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_du_singe)

-
Edité par lmghs 19 décembre 2018 à 16:51:48

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
19 décembre 2018 à 16:59:24

Fvirtman a écrit:

Non, visiblement, il ne garde que le dernier (vérifié en debug) . C'est comme si tu avais rentré '1' le 4 est ignoré.

It's a trap!

Les warnings de GCC :

prog.cc:6:29: warning: multi-character character constant [-Wmultichar]
    6 |     const char *s1=new char('41');
      |                             ^~~~
prog.cc: In function 'int main()':
prog.cc:6:33: warning: overflow in conversion from 'int' to 'char' changes value 
from '13361' to ''1'' [-Woverflow]
    6 |     const char *s1=new char('41');
      |     

La doc citée par CeBiM correspond aux représentations binaires (donc avec \), ce qui n'est pas le cas ici.

Ici, c'est juste du n'importe quoi. Le '41' est interprété comme un int. Et comme la valeur ne passe pas dans un char, ca devient 1. Mais c'est random.

Cf mon cours : http://guillaume.belz.free.fr/doku.php?id=chaines (j'ai utilisé un autre exemple et la valeur est différente).

Conclusion :

  • lire un cours correct, qui explique ce type d'erreur
  • activer les warnings dans le compilateur

EDIT : du coup, CeBiM, ce n'est pas ça. C'est romantik qui a raison.

lmghs a écrit:

(EDIT: WTF?! Ca compile ?!)

Tu ne savais pas que ca compile ? Ca... veut... dire...

Tu n'as pas lu mon cours ? #Shame! :)

-
Edité par gbdivers 19 décembre 2018 à 17:04:17

  • Partager sur Facebook
  • Partager sur Twitter
19 décembre 2018 à 19:15:13

Merci à tous pour votre intervention d'abord.

La réponse donnée par romantik, me semble la réponse la plus précise. 

J'ai lu la doc envoyée par  @romantik.

QUelqu'un saurait-il m'expliquer la transformation de '41' en 1 sur une implémentation 64 bits ?

Merci

  • Partager sur Facebook
  • Partager sur Twitter
19 décembre 2018 à 19:21:09

T'as lu le dernier message de gbdivers ? Attend je vais t'eviter de lire .. 


Ici, c'est juste du n'importe quoi. Le '41' est interprété comme un int. Et comme la valeur ne passe pas dans un char, ca devient 1. Mais c'est random.

Cf mon cours : http://guillaume.belz.free.fr/doku.php?id=chaines (j'ai utilisé un autre exemple et la valeur est différente).

Conclusion :

lire un cours correct, qui explique ce type d'erreur
activer les warnings dans le compilateur
EDIT : du coup, CeBiM, ce n'est pas ça. C'est romantik qui a raison.
  • Partager sur Facebook
  • Partager sur Twitter
19 décembre 2018 à 19:25:11

implementation-defined veut dire que clang, clang++, icc, icpc, vc++, gcc, g++, turbo C++, edg, et j'en passe peuvent tous choisir de faire une chose différente, et ils peuvent même choisir des choses différentes d'une machine à l'autre, d'une année à l'autre, en 16,32,64... bits.

Bref, ils font ce qu'ils veulent et il n'est pas attendu d'eux qu'ils refusent la compilation (si je ne me trompe pas -- quoique j'ai un doute). Mais refuser la compilation aurait très certainement été la chose intelligente à faire.

Donc t'expliquer pourquoi tu as choppé un 1? Aucune idée. Il y a trop de paramètres, de choix possibles. Quoique pour être honnête, implementation-defined veut dire que les complilos ont le droit de faire ce qu'ils veulent, mais que le choix doit être documenté. Donc quelque part, une explication existe. google est ton ami -- perso, l'information ne présente aucun intérêt, je ne veux même pas savoir.

IOW, honnêtement, on s'en fout. Ce bout de code n'aurait jamais du être valide car il n'a aucun sens.

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
19 décembre 2018 à 22:57:12

gbdivers a écrit:

Ici, c'est juste du n'importe quoi. Le '41' est interprété comme un int. Et comme la valeur ne passe pas dans un char, ca devient 1. Mais c'est random.

Cf mon cours : http://guillaume.belz.free.fr/doku.php?id=chaines (j'ai utilisé un autre exemple et la valeur est différente).

Dans le premier cas, comme ton compilateur le montre, nous avons un overflow d'une valeur 13361d soit 0x34 31.

Or, en table ASCII, 0x34 = 52d = '4' et 0x31 = 49d = '1'.

Dans le cas de ton cours, pour 'hello, world!', nous avons la valeur 1919706145d soit 0x‭72 6C 64 21‬  (car la conversion s'est faite sur un entier, donc de quoi stocker 4 octets soit 4 caractères... comme "rld!" par exemple).

0x72 = 114d = 'r', 0x6C = 108d = 'l'... Bref je vous laisse faire les suivant ! Vous avez compris l'idée.

Et si 'hello, world!' était "forcé" à être converti en char, tu aurais eu '!'.

La façon dont un compilateur fait ça dépend sans doute du compilateur, oui. Mais non, ce n'est pas aléatoire, c'est un comportement, que ce soit pour le compilateur de YES, man, celui de gbdivers ou le mien, défini et prédictible (et apparemment le même d'ailleurs).

Après, pour l'utilité, ça devait peut être servir il y a 30 ans... Mais maintenant, cette "technique de conversion" a juste l'air d'être une relique du passé, bien inutile comme dit au dessus.

lmghs a écrit:

perso, l'information ne présente aucun intérêt, je ne veux même pas savoir.

 Désolé !



  • Partager sur Facebook
  • Partager sur Twitter
19 décembre 2018 à 23:52:07

J'avais bien imaginé ça, mais comme dit lmghs, osef complètement.
  • Partager sur Facebook
  • Partager sur Twitter
19 décembre 2018 à 23:56:03

Donc, en gros, si je comprends, le compilateur fait une troncature au premier char en fait ... j'ai l'impression en fait.
  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 0:02:22

Osef ce qu'il fait. Il donner un warning, qui dit qu'il ne faut pas faire ça. C'est tout ce qu'il faut savoir.
  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 0:04:33

Quelle option actives-tu dans les warning pour avoir ce warning car je ne l'ai pas ?

-
Edité par pseudo-simple 20 décembre 2018 à 0:06:50

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 0:08:12

"-Wall -Wextra" sont un bon point de départ pour les compilos g++ et clang++
  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
20 décembre 2018 à 0:08:17

Pour les débutants, je conseille "-Weverything -Wno-c++98-compat". Si on a des warnings qu'on ne comprend pas, on demande sur le forum si le code est bon quand meme.

Moins voilent, cf le GitHub de jo_link_noir : https://github.com/jonathanpoelen/cpp-compiler-options 

-
Edité par gbdivers 20 décembre 2018 à 0:09:51

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 8:45:42

@gbdivers : Je plussoie !

Encore un soir où je me coucherai moins con ^^

-
Edité par CeBiM 20 décembre 2018 à 9:09:41

  • Partager sur Facebook
  • Partager sur Twitter
Les seules questions bêtes sont celles qui ne sont pas posées. Mieux vaut paraître bête une fois que de le rester à vie."Vis comme si tu devais mourir demain. Apprends comme si tu devais vivre toujours."
20 décembre 2018 à 10:37:57

Bonjour,

Avec ces options que vous avez indiquées, le compilateur n'envoie pas les warnings.

Quelle est l'option à ajouter pour avoir le truc le plus exigeant dans les warnings ?

-
Edité par pseudo-simple 20 décembre 2018 à 10:55:50

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 11:14:47

Bizarre, on dirait que c'est automatique... https://gcc.godbolt.org/z/s3lJ0f

C'est quoi ton compilateur?

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
20 décembre 2018 à 11:22:49

celui dans codeblocks :

indiqué g++

dans le répertoire :

\mingw-w64\x86_64\mingw64

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 11:25:53

Je serais surpris qu'on ne t'a pas deja dit de mettre a jour ton mingw, voir de ne pas utiliser Code::Block. Pour mettre a jour : https://openclassrooms.com/forum/sujet/mettre-a-jour-le-mingw-gcc-de-code-blocks
  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 13:32:51

Merci gbdivers et les autres. Même si j'avais déjà mis à jour depuis longtemps mon gcc, ton intervention m'a permis de résoudre un problème qui m'était posé depuis assez longtemps par codeblocks.

En effet, jadis, à chaque fois que je mettais à jour les informations de paramétrage du compilateur, j'avais remarqué qu'il fallait attendre plusieurs heures, pour que ces mêmes informations soient appliquées sur mes projets.

Je faisais "build & run" directement juste après avoir mis à jour les informations de paramétrage. Et ces informtions n'étaient pas pris en compte immédiatement.

Aujourd'hui, pour pouvoir faire en sorte d'avoir le message du compilateur, j'ai ajouté la longue liste de -W... proposée dans le lien que tu as envoyé.

J'ai mis à jour, fait OK, puis mon fameux "build & run", et les nouveautés n'étaient pas appliquées.

Or en faisant un "rebuild" (option juste à côté de "build & run") avant de faire "build & run", je découvre avec plaisir que mes modifications sont toutes appliquées dans le paramétrage et immédiatement.

1) Est- ce que l'étape "build" correspond bien à la phase d'assemblage(passage de l'assembleur au point .o) ou  l'édition de lien ? et rebuild alors dans ce cas ?

2) Et que se passe -t-il de si particulier pendant un rebuild qui fait que toutes mes modifications de paramétrage sont appliquées de manière si agréable ?

Merci pour vos explications 

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 13:49:58

Et quand on te dit que tu n'as pas les bases suffisantes pour comprendre le bouquin de Scott Meyers, tu envoies bouler les intervenants...

Tu ne sais meme pas comment fonctionne la chaine de compilation et d'édition de liens ?

  • Partager sur Facebook
  • Partager sur Twitter

Si vous ne trouvez plus rien, cherchez autre chose.

20 décembre 2018 à 13:53:12

YES, man a écrit:

1) Est- ce que l'étape "build" correspond bien à la phase d'assemblage(passage de l'assembleur au point .o) ou  l'édition de lien ? et rebuild alors dans ce cas ?

2) Et que se passe -t-il de si particulier pendant un rebuild qui fait que toutes mes modifications de paramétrage sont appliquées de manière si agréable ?

Il re-génère les fichiers

-
Edité par Garfounk 20 décembre 2018 à 13:53:31

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 14:04:56

@dragonjoker, avec tes réponses insensées, tu ne m'aides pas à progresser. Si tu veux m'aider concrètement, tu peux répondre à mes 2 questions au lieu de balancer ta négativité dévalorisante.

1) Est- ce que l'étape "build" correspond bien à la phase d'assemblage(passage de l'assembleur au point .o) ou  l'édition de lien ? et rebuild alors dans ce cas ?

2) Et que se passe -t-il de si particulier pendant un rebuild qui fait que toutes mes modifications de paramétrage sont appliquées directement ?

-
Edité par pseudo-simple 20 décembre 2018 à 14:05:42

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 14:08:28

YES, man a écrit:

1) Est- ce que l'étape "build" correspond bien à la phase d'assemblage(passage de l'assembleur au point .o) ou  l'édition de lien ? et rebuild alors dans ce cas ?

2) Et que se passe -t-il de si particulier pendant un rebuild qui fait que toutes mes modifications de paramétrage sont appliquées directement ?

"Il re-génère les fichiers" - Garfounk, 2018.
  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 14:58:58

YES, man a écrit:

1) Est- ce que l'étape "build" correspond bien à la phase d'assemblage(passage de l'assembleur au point .o) ou  l'édition de lien ? et rebuild alors dans ce cas ?

2) Et que se passe -t-il de si particulier pendant un rebuild qui fait que toutes mes modifications de paramétrage sont appliquées de manière si agréable ?

1) A ma connaissance, seul ce qui à besoin d'être mis à jour est compilé, d'où le fait que les changement de configuration du compilateur ne produisent pas toujours un effet.

2)Tout est recompilé.

Note:
Si ton IDE le propose, tu peux également nettoyer ton projet avant de le compiler.
Cette opération supprime tous les fichiers générés pendant la compilation.

YES, man a écrit:

@dragonjoker, avec tes réponses insensées, tu ne m'aides pas à progresser. Si tu veux m'aider concrètement, tu peux répondre à mes 2 questions au lieu de balancer ta négativité dévalorisante.

Malheureusement, dragonjoker à raison, la preuve est que tu l'envoies bouler.

J'ai lu le livre de Scott Meyers:
Ai-je tout compris ? Non.
Ai-je le niveau pour tout comprendre ? Non.
Suis-je débutant: Non.
Cela me sera t'il utile dans mes devs ? Peut être 1% des cas.

Les même réponses peuvent s'appliquer à ton cas, sauf pour une seule question:
Es-tu débutant: Oui.

Donc devient d'abord développeur confirmé, ensuite plonge toi dans le livre.

-
Edité par Deedolith 20 décembre 2018 à 15:06:38

  • Partager sur Facebook
  • Partager sur Twitter
20 décembre 2018 à 15:38:17

En tant que développeur confirmé (ça fait plus de 20 ans que je programme) les questions du livre de Scott Meyers me posent des colles. 

Bon, je trouve ça rigolo de se faire coller et d'essayer de comprendre ces bizarreries. C'est pour ça que je fais quelques tests et je réponds.

Mais en effet, j'ai du mal à comprendre pourquoi un débutant emprunte une telle voie...  J'en avais déjà parlé quand je parlais du verbe choir au plus que parfait du subjonctif.

-
Edité par Fvirtman 20 décembre 2018 à 15:38:44

  • Partager sur Facebook
  • Partager sur Twitter

Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

20 décembre 2018 à 15:48:24

Le bouton build de C::B lance la compilation/link de ton projet, en fonction des fichiers que tu as modifiés depuis la dernière fois où tu as cliqué sur ce même bouton.

Il y a donc plusieurs choses qui se passent lorsque tu cliques sur ce bouton : Compilation des fichiers (compilation des sources en .o, pas d'assembleur ici... Oh wait !), Edition des liens (assemblage des .o par le linker pour obtenir le fichier .a/.lib/.so/.dll/exécutable)

Comme tout le monde n'a de cesse de te le répéter, tu n'as pas le niveau par ce bouquin, tu n'as apparemment même pas les bases...

  • Partager sur Facebook
  • Partager sur Twitter

Si vous ne trouvez plus rien, cherchez autre chose.

20 décembre 2018 à 15:54:21

Arrêtez de me dénigrer ! Vous n'arriverez pas à me convaincre ! Ma méthode est bonne ! Cela prend juste du temps, mais un jour je serais le meilleur développeur C++ ! Je me battrai sans répit ! Je ferai tout pour être vainqueur et gagner les défis ! Je parcourrai la terre entière, traquant avec espoir le C++ et ses mystères !
  • Partager sur Facebook
  • Partager sur Twitter