problème avec le langage c
Répondre à la discussion
Page 1 sur 2 1 DernièreDernière
Affichage des résultats 1 à 30 sur 32

problème avec le langage c



  1. #1
    invite7fe20698

    Red face problème avec le langage c


    ------

    je suis débutant en programmation et j'ai voulu créé un programme qui me permet de convertir les nombre décime en binaire, aprés avoir écrit le programme avec des conditions l'affichage ne correspond pas aux affectations que j'ai faites
    voila le programme je lai fait que pour 0 et 2
    Code:
    #include <stdio.h>
    int X;
    int T;
    main() {
    printf("X=");
    scanf("%d",&X);
    if(X==0) { T=0000;
    printf("T=%d",T);
    } 
    if(X==2) { T=0101;
    printf("T=%d",T);
    }
    }
    merci de me dire ou est le problème ))

    -----
    Dernière modification par JPL ; 14/10/2018 à 22h12. Motif: Ajout de la balise Code (#)

  2. #2
    Jack
    Modérateur

    Re : problème avec le langage c

    Si tu comptes traiter tous les nombres à l'aide de "if", tu n'as pas fini ...

    Il te faut trouver un algorithme pour la conversion: le plus simple est d'effectuer une succession de divisions entières par 2, comme on le ferait avec un papier et un crayon.

    Concernant ton problème, bien que tu ne précises pas vraiment ce qui te perturbe, je suppose que pour X=2, ça t'affiche 65. C'est normal, car le fait de commencer un nombre par 0 indique que ce nombre est codé en octal, et 101 en octal est égal à 65 en décimal.

    A+

    PS: indente tes programmes, utilise les balises code la prochaine fois. Par convention, en tout cas la plupart du temps, on ne commence pas un nom de variable par une majuscule.

  3. #3
    invite7fe20698

    Re : problème avec le langage c

    vous avez raison ça s'affiche 65 comment est ce qu je peux remédier ?

  4. #4
    Jack
    Modérateur

    Re : problème avec le langage c

    Si tu traites le résultat comme un nombre, les zéros non significatifs ne seront pas affichés.
    Traite le nombre binaire sous forme de chaîne de caractères.
    Dernière modification par Jack ; 15/10/2018 à 07h58.

  5. A voir en vidéo sur Futura
  6. #5
    PA5CAL

    Re : problème avec le langage c

    Bonjour

    Il est important de bien faire la distinction entre la valeur d'un nombre et sa représentation.

    Dans le code source du programme en langage C, la valeur du nombre « vingt » peut par exemple être représentée :
    - par des chiffres en base dix (représentation décimale) : 20
    - par un nombre et un exposant en base dix (notation scientifique) : 2e1
    - par des chiffres en base huit (représentation octale) : 024
    - par des chiffres en base seize (représentation hexadécimale) : 0x14
    Bien que cela ne soit pas standard, sur certains compilateurs C/C++ comme les dernières versions de GCC et Clang, il est aussi possible de la représenter par des chiffres en base deux (représentation binaire) : 0b00010100

    Par ailleurs, le fait d'écriture « vingt » en toutes lettres, « twenty » en anglais, « 二十 » en chinois ou « XX » en chiffres romains, ou encore le fait d'ouvrir deux fois ses dix doigts face à son interlocuteur, constituent également des représentations de cette même valeur.


    Dans le programme, une variable stocke la valeur d'un nombre, indépendamment des différentes façons de la représenter.

    Afficher cette valeur sur un écran consiste à en produire l'une des représentations possibles sous forme de caractères affichables. Le langage C permet de produire certaines de ces représentations au travers de la fonction printf, mais pour toutes les autres, il est nécessaire d'écrire des programmes spécifiques.

    Pour la représentation binaire, on procède généralement au calcul de la suite des chiffres qui produiront les caractères '0' ou '1' représentant la valeur.

    Voici un exemple de code qui donne la représentation binaire de nombres compris entre 0 et 255 :

    Code:
    #include <stdio.h>
    
    main() {
      unsigned int valeur, masque;
    
      printf("Valeur ? ");
      scanf("%d",&valeur);
    
      for (masque=0x80 ; masque!=0 ; masque>>=1) {
        if (valeur & masque)
          putchar('1');
        else
          putchar('0');
      }
    
      putchar('\n');
    }
    Dernière modification par PA5CAL ; 15/10/2018 à 13h31.

  7. #6
    inviteb0f2badd

    Re : problème avec le langage c

    Bonjour,

    en effet toutes les données sont en binaire en mémoire. C'est la représentation que l'on en fait qui diffère.

    Avec :

    printf("%b", 255);

    on affiche 11111111 soit 255.


    pour ton problème :
    Code:
    #include <stdio.h>
    
    main() {
     unsigned int valeur;
    
     printf("Valeur ? ");
     scanf("%d",&valeur);
    
     printf("%b \n", valeur);
    
    }

  8. #7
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par cyril34 Voir le message
    Avec :

    printf("%b", 255);

    on affiche 11111111 soit 255.
    Dans printf, l'indicateur de format « %b » n'est pas standard, au même titre que la notation « 0b... » que j'ai indiquée. Cela ne fonctionne qu'avec certains compilateurs, comme par exemple les dernières versions de GCC.

    Avec GCC version 4.2, la compilation donne encore le message « unknown conversion type character ‘b’ in format ».

  9. #8
    PHIGE

    Re : problème avec le langage c

    Bonjour

    Une petite "amélioration" possible (je n'aime pas trop les branchements) :
    Code:
    #include <stdio.h>
    
    main() {
      unsigned int valeur, masque;
    
      printf("Valeur ? ");
      scanf("%d",&valeur);
    
      for (masque=0x80 ; masque!=0 ; masque>>=1)  putchar('0'+ (valeur & masque!=0));  // 0x80 en 8 bits, 0x8000 en 16 bits, 0x8000000 en 32 bit etc. 
      putchar('\n');
    }
    C'est concis et assez peu lisible : tout ce que j'aime. En fait, je crois que je serais même passé par un tableau de char (genre char chars[33]) pour pouvoir écrire : for(int i=31; i>=0; --i) { chars[i] = '0'+ (valeur & 1); valeur >>= 1; } .

    Ces techniques binaires utilisent le faible typage du C. Elles sont utiles pour des opérations critiques mais leur faible lisibilité les rend peu maintenables. Pour une réponse en temps humain elles n'apportent rien : l'instantanéité humaine est au 1/10s, aussi passer, par exemple, de la ms à 100 us a un intérêt tout relatif.

    Mais savoir qu'elles existent peut être utile.
    Dernière modification par Jack ; 17/10/2018 à 12h41. Motif: Ajout balises code

  10. #9
    Jack
    Modérateur

    Re : problème avec le langage c

    Merci de penser à ajouter les balises code pour présenter correctement du code.

  11. #10
    Jack
    Modérateur

    Re : problème avec le langage c

    Citation Envoyé par PA5CAL Voir le message
    Dans printf, l'indicateur de format « %b » n'est pas standard, au même titre que la notation « 0b... » que j'ai indiquée. Cela ne fonctionne qu'avec certains compilateurs, comme par exemple les dernières versions de GCC.

    Avec GCC version 4.2, la compilation donne encore le message « unknown conversion type character ‘b’ in format ».
    Je ne m'explique d'ailleurs pas pourquoi le format binaire n'est pas pris en compte depuis l'origine, car le langage C est un langage de haut niveau sensé être capable de traiter des problèmes de bas niveau.
    Ce serait tout de même plus utile que l'octal, car à part la gestion des droits d'accès aux fichiers, l'octal présente assez peu d'intérêt. En tout cas, je n'en ai jamais eu besoin, alors que le binaire si.

  12. #11
    Fustigator

    Re : problème avec le langage c

    Citation Envoyé par Jack Voir le message
    Je ne m'explique d'ailleurs pas pourquoi le format binaire n'est pas pris en compte depuis l'origine, car le langage C est un langage de haut niveau sensé être capable de traiter des problèmes de bas niveau..
    L'affichage de nombre en format binaire n'est peut être pas forcément une nécessité courante; et par ailleurs, histoire de pinailler, ce n'est pas le langage ici qui pose une limitation mais la biblio standard de RT.

  13. #12
    Jack
    Modérateur

    Re : problème avec le langage c

    En tout cas, le C++ a fait le pas depuis C++14.

  14. #13
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par Fustigator Voir le message
    par ailleurs, histoire de pinailler, ce n'est pas le langage ici qui pose une limitation mais la biblio standard de RT.
    Histoire de pinailler un peu plus (et sans soulever la question de savoir si une bibliothèque standard relève du langage ou pas ), si la reconnaissance de « %b » dans les fonctions printf et consort relève bien d'une bibliothèque standard, la notation « 0b... » est quant à elle bien uniquement liée à la syntaxe. Un compilateur C classique ne saura simplement pas interpréter le « b » et ce qui suit, et produira une erreur pour indiquer la présence d'un suffixe invalide après la constante entière « 0 ».

    Il faut bien se dire que le langage C n'a pas été pensé pour traiter du binaire littéralement. Toutefois, ce n'est pas un point rédhibitoire, car comme il ne s'agit que de représentation de valeurs numériques, on peut tout-à-fait s'en passer et faire le travail autrement.

    Comparativement, ce langage présente par ailleurs beaucoup d'autres lacunes qui empêchent le développeur de pouvoir produire, à partir de son code source et de ses options de compilation, un programme répondant de façon sûre à certaines spécifications (utilisation de ressources, temps d'exécution, ...). Fort heureusement, pour y parvenir il est toujours possible de mélanger des codes écrits dans plusieurs langages.

  15. #14
    albanxiii
    Modérateur

    Re : problème avec le langage c

    Citation Envoyé par Jack Voir le message
    En tout cas, je n'en ai jamais eu besoin, alors que le binaire si.
    Pareil ici. Mais je trouve que le binaire et l'hexadécimal c'est kiff kiff. On visualise facilement 0x28 ou 0xC5 en binaire.
    Not only is it not right, it's not even wrong!

  16. #15
    Jack
    Modérateur

    Re : problème avec le langage c

    Oui, tu as raison, je vois également immédiatement quels sont les bits à un dans un octet exprimé en hexadécimal, mais est-ce le cas pour tous?
    Un code source doit être le plus expressif possible. Lorsqu'on définit un masque par exemple, çà peut être plus lisible d'écrire 0b00000010 au lieu de 0x02. Quoique ...
    Enfin bref, si le C++ l'a ajouté récemment, c'est qu'il doit bien y avoir une raison.

  17. #16
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par Jack Voir le message
    Oui, tu as raison, je vois également immédiatement quels sont les bits à un dans un octet exprimé en hexadécimal, mais est-ce le cas pour tous?
    Avec un peu d'habitude, oui, très probablement.

    C'est comme apprendre le solfège : au début on a du mal, on doit réfléchir pour faire la transcription, mais après quelque temps, à force de pratique, cette transcription finit par être immédiate. Seize correspondances à retenir par cœur, ça ne fait pas beaucoup.

    Citation Envoyé par Jack Voir le message
    Enfin bref, si le C++ l'a ajouté récemment, c'est qu'il doit bien y avoir une raison.
    Certainement, et dans le cas présent le fait qu'on soit souvent amené à manipuler des bits paraît être une bonne raison.

    Toutefois, d'une manière plus générale, je ne vois pas d'un très bon œil l'évolution des standards, dans le sens où l'on suggère qu'on a toujours affaire aux mêmes standards, mais améliorés. Car pour un langage (au sens strict comme au sens large, avec les biblios), la portabilité du code représente souvent un objectif prioritaire.

    Or, imposer une évolution à un standard, c'est en toute rigueur créer un standard différent du premier. Au mieux, on perd la compatibilité ascendante des outils, et on doit faire évoluer ces derniers pour pouvoir accepter du code récent. Et si des éléments du langage sont frappés d'obsolescence, alors on perd aussi la rétrocompatibilité des nouveaux outils (au minimum quand on leur impose de respecter le standard), et on est alors forcé de procéder à l'adaptation du code ancien.

    On perd le bénéfice d'une totale portabilité, à savoir thésauriser les développements afin de les réutiliser et de les partager sans coût supplémentaire. Certains diront que ça fait marcher le business, mais c'est à l'opposé de l'objectif supposé d'un standard.


    À la limite, cela poserait moins de problème s'il était clairement admis que le nom générique d'un langage ne suffit pas à le définir jusque dans les détails, ou qu'une nouvelle version d'un langage normalisé ne constitue plus vraiment le même langage. On garderait alors à l'esprit que ce n'est pas parce qu'un code fourni est écrit « dans le langage » qu'il est utilisable tel quel. Le bout de code « en langage C » donné au post #6 en est un bon exemple.

  18. #17
    Jack
    Modérateur

    Re : problème avec le langage c

    Citation Envoyé par PA5CAL Voir le message
    Avec un peu d'habitude, oui, très probablement.

    C'est comme apprendre le solfège : au début on a du mal, on doit réfléchir pour faire la transcription, mais après quelque temps, à force de pratique, cette transcription finit par être immédiate. Seize correspondances à retenir par cœur, ça ne fait pas beaucoup.
    Tu prêches pour un convaincu .

    Quant à l'évolution des normes, en principe la rétrocompatibilité est assurée, mis à part certaines disparition de certaines fonctionnalités obsolètes ou jugées "dangereuses". ce n'est pas en ajoutant un formatage binaire dans une nouvelle version d'un compilateur que les anciens programmes ne compileront plus.

    Concernant le post#6, le problème vient justement du fait qu'il n'est pas écrit en langage C puisque n'étant reconnu par aucune norme du C. Si ne format est reconnu un jour, tous les nouveau programme pourront être compilés avec un compilateur à jour, et tous les anciens également, on a donc rien perdu et on continue de programmer en C avec une version évoluée.

  19. #18
    PA5CAL

    Re : problème avec le langage c

    Comme je l'ai indiqué, ma remarque portait plus généralement sur les standards, pas spécifiquement sur le langage C ni forcément sur des standards définis par des normes institutionnelles.

    Citation Envoyé par Jack Voir le message
    Quant à l'évolution des normes, en principe la rétrocompatibilité est assurée, mis à part certaines disparition de certaines fonctionnalités obsolètes ou jugées "dangereuses". ce n'est pas en ajoutant un formatage binaire dans une nouvelle version d'un compilateur que les anciens programmes ne compileront plus.
    L'ajout du format « 0b... » aux normes du C pose bien évidemment juste un problème de non reconnaissance des nouveaux codes par les compilateurs plus anciens.

    Concernant la rétrocompatibilité, elle n'est plus totale dès lors que des éléments sont modifiés ou retirés du standard, quelle qu'en soit la justification. Sur ce point, les standards industriels sont d'ailleurs beaucoup plus touchés que les standards issus de normes institutionnelles (qui découlent généralement de standards industriels ayant d'abord connu le succès). De nombreux outils n'assurent pas la rétrocompatibilité (qui n'a pas sué en changeant de version de Python ou de PHP ?! ), et même lorsqu'ils le font (via des options de compilation adéquates, par exemple), le problème se pose tout de même quand le cahier des charges impose le respect d'un standard déterminé.

    Citation Envoyé par Jack Voir le message
    Concernant le post#6, le problème vient justement du fait qu'il n'est pas écrit en langage C puisque n'étant reconnu par aucune norme du C. Si ne format est reconnu un jour, tous les nouveau programme pourront être compilés avec un compilateur à jour, et tous les anciens également, on a donc rien perdu et on continue de programmer en C avec une version évoluée.
    Le langage C a existé (Ritchie & Thompson en 1972) et est devenu un standard (Kernighan & Ritchie à partir de 1978) avant de commencer à être normalisé (ANSI à partir de 1983, ISO/CEI à partir de 1994).

    À mon sens, l'existence d'une norme institutionnelle n'est pas constitutif de la réalité d'un langage informatique. D'ailleurs, dans ma carrière j'ai passé beaucoup moins de temps à coder en langage C normalisé (C89 à C11) qu'en langage C obéissant à d'autres standards (de même s'agissant de C++), le plus souvent juste parce que les compilateurs n'étaient pas conformes à 100% aux normes.

    Il ne me semble donc pas pertinent d'exclure du champ des langages C ceux qui ne correspondent pas à l'une des normes institutionnelles. Cela reviendrait notamment à interdire de donner cette dénomination au langage produit par ses inventeurs .

    De mon point de vue, le code du post #6 est bien écrit en langage C. Et cela me semble faire sens car le langage C du GCC de GNU est aujourd'hui devenu un standard très largement répandu.

    En revanche, mon propos est qu'il est important d'arrêter de parler de langage C comme s'il n'y en avait qu'un seul (parce que c'est plutôt un concept générique), et d'arrêter de penser que les différents langages C, normalisés ou non, seraient les mêmes après une évolution de leur version.

    Ainsi, lorsqu'un exemple de code ne répond qu'à certains standards, et notamment des standards non normalisés, il me paraît important de préciser lesquels (éditeur et version).

    Citation Envoyé par Jack Voir le message
    Si ne format est reconnu un jour, tous les nouveau programme pourront être compilés avec un compilateur à jour, et tous les anciens également, on a donc rien perdu et on continue de programmer en C avec une version évoluée.
    S'il est normalisé un jour, j'en serais ravi, d'autant plus que cet ajout n'entamerait en rien la rétrocompatibilité.

    En ce qui me concerne, comme la majorité de mes développements font aujourd'hui appel à GCC, je n'ai pas attendu pour en profiter.
    Dernière modification par PA5CAL ; 18/10/2018 à 14h06.

  20. #19
    polo974

    Re : problème avec le langage c

    Citation Envoyé par Jack Voir le message
    Je ne m'explique d'ailleurs pas pourquoi le format binaire n'est pas pris en compte depuis l'origine, car le langage C est un langage de haut niveau sensé être capable de traiter des problèmes de bas niveau.
    Ce serait tout de même plus utile que l'octal, car à part la gestion des droits d'accès aux fichiers, l'octal présente assez peu d'intérêt. En tout cas, je n'en ai jamais eu besoin, alors que le binaire si.
    Ouais, bon, pour voir si on a le bit 48 ou 47 levé dans un champs de bit de 64 de large, c'est pas cool...
    Le binaire, brut de fonderie, ça va sur un octet, voire 2, mais imaginez une IP V6 en binaire...

    Les droits d'accès sont un champ de bits, mais il vient de si loin qu'il était représenté en octal...
    On pourrait aussi bien les représenter en hexa, mais on perdrait le groupage par 3 (wrx).

    L'octal était très utilisé en numération générale avant l'héxa. .
    Par exemple, les SNLE avaient une unité centrale travaillant sur 15 bits de data, soit 5 digits en octal.

    Article intéressant sur wiki-en: https://en.wikipedia.org/wiki/Octal
    Jusqu'ici tout va bien...

  21. #20
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par polo974 Voir le message
    Ouais, bon, pour voir si on a le bit 48 ou 47 levé dans un champs de bit de 64 de large, c'est pas cool...
    Le binaire, brut de fonderie, ça va sur un octet, voire 2, mais imaginez une IP V6 en binaire...
    Je doute qu'il viendrait à quelqu'un l'idée d'écrire une adresse IP v6 en binaire, compte tenu du peu d'intérêt que ce la représente. Mais il est très courant d'avoir à construire la valeur correspondant aux bits d'un masque ou d'un registre de configuration sur 1 ou 2 octets, parfois 4. Les champs de 8 octets sont beaucoup plus rares. Quoi qu'il en soit, des artifices d'écriture permettent encore de profiter des avantages de la notation binaire lorsque le nombre de bits devient important, à savoir la possibilité de faire figurer directement l'information dans le code source, sans calcul, afin de faciliter l'écrire, l'ajout de commentaires et la relecture.

    Voici par exemple l'initialisation d'un registre de 64 bits (33 bits utiles dans le cas présent) avec les commentaires correspondants :
    Code:
    // Hypervisor Configuration Register
    // configuration control for virtualization
    
      HCR_EL2 =
    //         +-- [63:34] (reserved)
    //         |+-- ID Stage 2 instruction cache disable
    //         |!+- CD Stage 2 data cache disable
    //         |!|
       (0b00000000ULL <<32) |
    
    //    +-- RW Register width control
    //    |+-- TRVM Trap reads of Virtual Memory controls
    //    |!+-- HCD (reserved)
    //    |!|+-- TDZ Trap DC ZVA instruction
    //    |!|!+-- TGE Trap general exceptions
    //    |!|!|+-- TVM Trap virtual memory controls
    //    |!|!|!+-- TTLB Trap TLB maintenance instructions
    //    |!|!|!|+--TPU Trap cache maintenance instructions to PoU
    //    |!|!|!|!
       (0b00000000ULL <<24) |
    
    //    +-- TPC Trap data/unified cache maintenance instructions to PoC
    //    |+-- TSW Trap data/unified cache maintenance instructions by SoW
    //    |!+-- TACR Trap Auxiliary Control registers
    //    |!|+-- TIDCP Trap Implementation Dependent functionality
    //    |!|!+-- TSC Trap SMC instruction
    //    |!|!|+-- TID3 Trap ID group 3 registers
    //    |!|!|!+-- TID2 Trap ID group 2 registers
    //    |!|!|!|+-- TID1 Trap ID group 1 registers
    //    |!|!|!|!
       (0b00000000ULL <<16) |
    
    //    +-- TID0 Trap ID group 0 registers
    //    |+-- TWE Trap WFE instruction on suspension of execution
    //    |!+-- TWI Trap WFI instruction on suspension of execution
    //    |!|+-- DC Default cacheable
    //    |!|! +-- BSU[1:0] Barrier shareability upgrade
    //    |!|! |+-- FB Forces broadcast
    //    |!|! |!+-- VSE Virtual System Error/Asynchronous Abort
    //    |!|! |!|
       (0b00000000ULL <<8) |
    
    //    +-- VI Virtual IRQ interrupt
    //    |+-- VF Virtual FIQ interrupt
    //    |!+-- AMO Asynchronous abort and error interrupt routing
    //    |!|+-- IMO Physical IRQ routing
    //    |!|!+-- FMO Physical FIQ routing
    //    |!|!|+-- PTW Protected Table Walk
    //    |!|!|!+-- SWIO Set/Way Invalidation Override
    //    |!|!|!|+-- VM Enables second stage of translation
    //    |!|!|!|!
       (0b00000000ULL);
    (Il n'y a plus qu'à "remplir les cases". Le calcul de la valeur constante sur 64 bits n'est pas réalisé à l'exécution mais à la compilation.)
    Dernière modification par JPL ; 18/10/2018 à 22h10. Motif: correction de balise

  22. #21
    Tryss2

    Re : problème avec le langage c

    Intéressante cette présentation ! je la réutiliserai dorénavant pour documenter ce genre de trucs (ça marche aussi pour autre chose que le binaire)

  23. #22
    Jack
    Modérateur

    Re : problème avec le langage c

    C'est ainsi que je procède également pour programmer mes microcontrôleurs, ceux-ci possédant de nombreux registres à configurer où chaque bit ou groupe de bits possède une signification.

  24. #23
    polo974

    Re : problème avec le langage c

    Pas mal comme présentation, ça documente en même temps.

    De mon coté, je suis plus porté sur l'usage de macros, un peu comme dans les flags passés à open et autres... mais parfois, on doit fouiller loin dans les headers pour trouver les valeurs qui se cachent derrière...
    Jusqu'ici tout va bien...

  25. #24
    PHIGE

    Re : problème avec le langage c

    Bonjour,

    Il y a aussi les champs binaires qui peuvent être bien pratiques à condition de savoir dans quel ordre le compilateur aura le bon goût de les mettre (l'avantage est que ça marche aussi pour des groupes de bits).
    Code:
    struct Champs {
       unsigned b0  :1;   // On peut donner des noms plus explicites (c'est l'un des intérêts)
       unsigned b1_3:3;
       unsigned b4  :1;
       unsigned b5  :1;
       unsigned b6_7:2;
       ...
       }
    Et puis il y a aussi l'assembleur inline avec ses opérateurs bit (bt pour bit test, btc teste et complémente, btr teste et met à 0, bts teste et met à 1).

    Il y a de quoi s'amuser.

    Bien sûr, il n'y a pas de meilleure méthode. Tout dépend de ce que veut faire. Utiliser de l'assembleur pour initialiser serait au mieux ridicule.
    Dernière modification par PHIGE ; 19/10/2018 à 15h57. Motif: Erreur sur taille du second champ

  26. #25
    Jack
    Modérateur

    Re : problème avec le langage c

    En effet, et grâce aux unions (leur utilisation n'est pas si courante), on peut accéder soit à l'octet complet, soit aux bits individuels, soit au groupes de bits des champs. Par exemple:
    Code:
    /*** PTAD - Port A Data Register; 0x00000000 ***/
    typedef union {
      byte Byte;
      struct {
        byte PTAD0       :1;                                       /* Port A Data Register Bit 0 */
        byte PTAD1       :1;                                       /* Port A Data Register Bit 1 */
        byte PTAD2       :1;                                       /* Port A Data Register Bit 2 */
        byte PTAD3       :1;                                       /* Port A Data Register Bit 3 */
        byte PTAD4       :1;                                       /* Port A Data Register Bit 4 */
        byte PTAD5       :1;                                       /* Port A Data Register Bit 5 */
        byte             :1; 
        byte             :1; 
      } Bits;
      struct {
        byte grpPTAD :6;
        byte         :1;
        byte         :1;
      } MergedBits;
    } PTADSTR;

  27. #26
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par PHIGE Voir le message
    à condition de savoir dans quel ordre le compilateur aura le bon goût de les mettre
    C'est la raison pour laquelle on évite le plus souvent de les utiliser en dehors des cas où l'on cherche juste à gagner de la place.

    Pour donner un exemple :
    Code:
    #include <stdio.h>
    
    main() {
      struct {
        unsigned b0 : 1;
        unsigned b1 : 1;
        unsigned b2 : 1;
        unsigned b3 : 1;
        unsigned b4 : 1;
        unsigned b5 : 1;
        unsigned b6 : 1;
        unsigned b7 : 1;
        unsigned b8 : 1;
        unsigned b9 : 1;
        unsigned b10 : 1;
        unsigned b11 : 1;
        unsigned b12 : 1;
        unsigned b13 : 1;
        unsigned b14 : 1;
        unsigned b15 : 1;
      } a;
    
      *(unsigned *)&a = 0x956A;
      printf("%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u\n",
        a.b15, a.b14, a.b13, a.b12, a.b11, a.b10, a.b9, a.b8,
        a.b7, a.b6, a.b5, a.b4, a.b3, a.b2, a.b1, a.b0);
    }
    Compilé sous GCC v4, ce code affiche 1001010101101010 (soit 0x956A) sur un Mac Intel, mais 0000000000000000 sur un Mac G4 (PowerPC).

    La raison en est que sur le G4, les entiers sont par défaut stockés sur 32 bits, et que les bit fields définis dans la structure sont rangés dans les bits de poids fort.

    Pour régler ce problème, on peut expressément utiliser des entiers sur 16 bits :
    Code:
    #include <stdio.h>
    
    main() {
      struct {
        unsigned short b0 : 1;
        unsigned short b1 : 1;
        unsigned short b2 : 1;
        unsigned short b3 : 1;
        unsigned short b4 : 1;
        unsigned short b5 : 1;
        unsigned short b6 : 1;
        unsigned short b7 : 1;
        unsigned short b8 : 1;
        unsigned short b9 : 1;
        unsigned short b10 : 1;
        unsigned short b11 : 1;
        unsigned short b12 : 1;
        unsigned short b13 : 1;
        unsigned short b14 : 1;
        unsigned short b15 : 1;
      } a;
    
      *(unsigned short *)&a = 0x956A;
      printf("%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u\n",
        a.b15, a.b14, a.b13, a.b12, a.b11, a.b10, a.b9, a.b8,
        a.b7, a.b6, a.b5, a.b4, a.b3, a.b2, a.b1, a.b0);
    }
    On affiche toujours 1001010101101010 (soit 0x956A) sur le Mac Intel, mais sur le Mac G4 (PowerPC), on obtient 0101011010101001 (soit 0x56A9) : contre toute attente, les bit fields de la structure ne sont pas rangés dans l'ordre d'écriture !

    Cela n'est pas dû à une erreur d'exécution ni à une erreur dans la génération du programme par le compilateur GCC v4, mais au fait que le langage C ne définit pas ni n'apporte de garantie d'aucune sorte dans la façon dont les bit fields doivent être stockés en mémoire.

    En l'occurrence, le même compilateur ne les a pas rangés de la même manière sur les deux plateformes cibles.

    Autant dire que cela pose d'énormes problèmes de portabilité du code !
    Dernière modification par PA5CAL ; 19/10/2018 à 16h56.

  28. #27
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par PHIGE Voir le message
    Et puis il y a aussi l'assembleur inline avec ses opérateurs bit (bt pour bit test, btc teste et complémente, btr teste et met à 0, bts teste et met à 1).

    Il y a de quoi s'amuser.

    Bien sûr, il n'y a pas de meilleure méthode. Tout dépend de ce que veut faire. Utiliser de l'assembleur pour initialiser serait au mieux ridicule.
    Même si j'avoue utiliser très souvent la possibilité d'intégrer de l'assembleur dans mon code C/C++ pour certains de mes besoins personnels, il faut bien admettre qu'en le faisant on atteint le degré zéro en termes de compatibilité et de portabilité.

    Outre le fait que cela n'a plus rien à voir avec du langage C (et nécessite donc des compétences supplémentaires de la part de la personne qui écrit et de celles qui relisent) et que le code source devient spécifique à la plateforme cible, l'intégration de parties en assembleur augmente le niveau de difficulté des développements et les risques encourus.

    En effet, la coexistence du code issu du C ou du C++ et le code issu de l'assembleur ne va pas de soi, et nécessite une parfaite maîtrise du comportement de la chaîne de compilation afin de réaliser un interfaçage correct entre les deux parties. Or, il n'est pas toujours possible de savoir ce qu'il convient de faire, ni de deviner si ce qui fonctionne un jour restera pérenne quand le programme ou l'outil de développement connaîtront des évolutions.

    Par exemple, il est difficile de prévoir si une variable locale en C/C++ sera finalement stockée en mémoire RAM ou dans des registres, alors que le mode d'adressage en assembleur nécessaire à son accès en dépend directement (il m'est ainsi arrivé d'avoir des programmes qui cessent de fonctionner parce que la zone de stockage d'une variable avait été incidemment modifiée, du fait de la mise-à-jour du compilateur, d'un réglage différent des options de compilation, ou de la modification du code C/C++).

    Il est par conséquent fortement conseillé d'établir une nette séparation, avant l'édition de liens, entre les codes issus des différents langages. L'intégration de commandes simples permettant de contrôler des ressources matérielles normalement inaccessibles en C/C++ (comme la manipulation du bit de contrôle d'interruption ou la réalisation de délais logiciels, par exemple) pourrait y faire exception, mais dans la pratique le fait de les regrouper dans des bibliothèques spécifiques à la plateforme évite d'avoir à intégrer directement du code assembleur dans le code en C/C++ (d'ailleurs, les éditeurs d'outils de développement fournissent déjà souvent de telles bibliothèques prêtes à l'emploi).
    Dernière modification par PA5CAL ; 19/10/2018 à 19h20.

  29. #28
    PHIGE

    Re : problème avec le langage c

    Bonjour,

    L'assembleur n'est utile que dans les cas de recherche d'efficacité maximale. L'optimal ne va pas avec une pleine compatibilité voire même la compatibilité d'une version de processeur à l'autre (non pas nécessairement que ce qui marche sur un CPU ne marchera sur le suivant mais ce ne sera peut être plus optimal). Prenons un exemple. Quand on charge une donnée depuis la mémoire, le CPU charge en fait une ligne de données en se disant que les probabilités que nous ayons besoin de données adjacentes est fort. Mais la taille de cette ligne n'est pas nécessairement la même d'un CPU à l'autre. Aussi, si on utilise un prefetch (préchargement forcé de lignes, pas au niveau du premier cache car le CPU s'en moque en général) pour amplifier l'anticipation des accès au données, l'optimal demanderait une version pour chaque longueur. Pourtant c'est intéressant offrant des gains substantiels pour l'accès mémoire (de l'ordre de 10% sur un traitement d'image, pas mal pour une seule instruction).

    La lisibilité de l'assembleur est nulle : on écrit plus de commentaires que de code. L’entre-laçage de code (éviter les interdépendance entre deux instructions consécutives) pour aider le CPU à optimiser son out of order est une horreur à relire.

    Je suis d'accord avec PASCAL, a priori il ne faut pas utiliser l'assembleur : long et difficile à écrire, très faible portabilité, difficile à maintenir. Mais utiliser la pleine puissance des CPU actuels est parfois nécessaire (par exemple les compilateurs utilisent très peu les jeux d'instruction SIMD (MMX, SSEx etc.). Un gain de 2 sur le temps de traitement d'une image de 50 Mo ne me laisse pas insensible.

    Concernant l'interfaçage avec le C, l'assembleur inline est plutôt bientôt bien servi par l'accès symbolique aux objets propres du programme.

    Sans inciter particulièrement à l'utiliser, je pense qu'il est important qu'un développeur connaisse au moins l'éventail des possibilités : la solution doit être adaptée au problème et non l'inverse sous prétexte qu'une seule technique est maîtrisée. Cela ne signifie qu'il doive tout maîtriser mais qu'il ait conscience des types de solutions qui répondent le mieux. Après, il fait son choix en connaissance de cause.

    Les bibliothèques sont intéressantes et les utiliser est un gain de temps. Jeter un coup d’œil à leur source n'est pas inutile : leur lecture peut être très pédagogique et quelquefois un critère de (non)choix.

    En résumé, il y a 1000 et une manières de tondre un œuf.

  30. #29
    PHIGE

    Re : problème avec le langage c

    Bonjour

    Pascal à écrit :
    En l'occurrence, le même compilateur ne les a pas rangés de la même manière sur les deux plateformes cibles.
    Je crois que le compilateur change l'ordre en fonction du BIG ENDIAN ou LITTLE ENDIAN, non pas qu'il en ait besoin à l'écriture, mais à la lecture il faut que ce soit dans l'ordre du naturel du CPU pour retrouver la valeur d'un groupe de bits (pour un seul c'est naturellement ordonné ).

    A vérifier, je ne connais pas les PowerPC.

  31. #30
    PA5CAL

    Re : problème avec le langage c

    Citation Envoyé par PHIGE Voir le message
    Je crois que le compilateur change l'ordre en fonction du BIG ENDIAN ou LITTLE ENDIAN, non pas qu'il en ait besoin à l'écriture, mais à la lecture il faut que ce soit dans l'ordre du naturel du CPU pour retrouver la valeur d'un groupe de bits (pour un seul c'est naturellement ordonné ).
    La différence entre big endian et little endian explique qu'on trouve 0x0000 dans le premier exemple, mais pas qu'on passe de 0x956A à 0x56A9 dans le second : si l'ordre des bits avait été respecté, on aurait dû plutôt trouver 0x6A95.

Page 1 sur 2 1 DernièreDernière

Discussions similaires

  1. [Programmation] langage c ==> problème avec while
    Par michelcreuse dans le forum Électronique
    Réponses: 6
    Dernier message: 31/01/2018, 17h48
  2. probleme avec le langage script
    Par invitebd580a5b dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 01/12/2010, 07h57
  3. langage C : problème avec scanf
    Par invitedba13d1f dans le forum Logiciel - Software - Open Source
    Réponses: 20
    Dernier message: 20/04/2009, 17h41
  4. problème avec le langage pascal
    Par invite49b54ac2 dans le forum Logiciel - Software - Open Source
    Réponses: 3
    Dernier message: 28/01/2009, 11h45
  5. problème avec langage C++
    Par invite0f6e0be6 dans le forum Logiciel - Software - Open Source
    Réponses: 5
    Dernier message: 03/10/2007, 11h20