Partage
  • Partager sur Facebook
  • Partager sur Twitter

Les mots clefs du C

Discussion sur le topic sur les mots clefs du C

    2 août 2012 à 0:17:52

    Citation : Mr21

    Mais j'ai plusieurs tour dans mon sac :


    Après, le résultat dépend des optimisations du compilateur:

    00:15:58 /tmp
    gcc c.c
    00:16:48 /tmp
    ./a.out 
    22
    22
    44
    0x7ffffa2ff774
    0x7ffffa2ff774
    22
    00:16:49 /tmp
    gcc -O3 c.c 
    00:16:52 /tmp
    ./a.out 
    22
    22
    42
    0x7fff327a1d8c
    0x7fff327a1d8c
    22
    00:16:53 /tmp
    • Partager sur Facebook
    • Partager sur Twitter
      2 août 2012 à 10:12:28

      Citation : Mr21

      Lucas, evidemment qu'en C99 ça sera possible! tu peux y mettre une variable entre crochet, donc constante ou pas le compilo s'en fout maintenant...



      Bah oui, et alors ? Je ne faisais que relever un passage qui n'était pas vrai à proprement parler. Pas besoin d'y passer des heures.
      • Partager sur Facebook
      • Partager sur Twitter
      Staff désormais retraité.
      Anonyme
        17 août 2012 à 16:15:19

        short, int, long

        Norme : toutes
        Description : ces trois mots-clefs permettent de déclarer un entier. Leurs bornes dépend de l'architecture. Cependant, la norme garantie des bornes minimales pour chacun des types :

        Citation : Norme C89 - 2.2.4.2

        Type Minimum Maximum
        short -32 767 32 767
        int -32 767 32 767
        long -2 147 483 647 2 147 483 647


        Les valeurs exactes sont retrouvables dans le fichier d'en-tête <limits.h>. Ce code permet de retrouver les bornes minimales et maximales réelles d'une architecture :

        #include <stdio.h>
        #include <limits.h>
        
        #define AFF(x)  printf("%s = %d\n", #x, x)
        
        int main(void)
        {
            AFF(SHRT_MIN);
            AFF(SHRT_MAX);
            AFF(INT_MIN);
            AFF(INT_MAX);
            AFF(LONG_MIN);
            AFF(LONG_MAX);
        
            return 0;
        }
        
        • Partager sur Facebook
        • Partager sur Twitter
          17 août 2012 à 16:35:28

          Citation : informaticienzero

          Un int correspond à un mot au niveau du processeur et fait donc la même taille. Si le processeur à un bus d'adresse de 16 bits, alors un int sera codé sur 16 bits. De même pour les processeurs 32 et 64 bits.


          Non, la taille du int n'est pas forcément celle des adresses. Ce n'est d'ailleurs pas le cas sur les systèmes courants.

          On peut encore noter que la notion de mot d'un processeur est un peu floue; parfois plusieurs tailles peuvent raisonnablement correspondre (comme 16 et 32 bits dans la famille M68k). C'est finalement décidé par ceux qui font l'ABI du système.
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            1 janvier 2013 à 23:45:44

            Histoire de remonter le projet pour savoir si ça intéresse toujours certaines personnes.

            sizeof

            Norme : toutes
            Description : Cet opérateur donne la taille en bytes d'un type, que ce soit un type primitif ou complexe.

            Petite remarque : le résultat de l'opérateur sizeof est de type size_t et non de type int ou unsigned int comme on serait tenter de le penser de prime abord. La raison est très simple : cela est dû aux bornes de ces types. En effet, pour connaitre la taille d'un type simple comme int ou char, les bornes d'un unsigned int ou d'un int ne pose pas de problèmes. Mais sizeof peut aussi servir pour récupérer autre chose comme la taille de données plus élaborées. Et sur certains ordinateurs, on peut parfaitement avoir des données dont la taille dépasse les bornes d'un unsigned int ou d'un int. Aussi, pour résoudre ce problème, le type size_t a été crée et permet de contenir la taille de n'importe quelle donnée.

            Exemple et / ou commentaire :

            #include <stdio.h>
            
            int main(void)
            {
                printf("Taille d'un char = %lu\n", (unsigned long) sizeof(char));
                printf("Taille d'un short = %lu\n", (unsigned long) sizeof(short));
                printf("Taille d'un int = %lu\n", (unsigned long) sizeof(int));
                printf("Taille d'un long = %lu\n", (unsigned long) sizeof(long));
                printf("Taille d'un float = %lu\n", (unsigned long) sizeof(float));
                printf("Taille d'un double = %lu\n", (unsigned long) sizeof(double));
                printf("Taille d'un long double = %lu\n", (unsigned long) sizeof(long double));
                return 0;
            }
            


            register

            Norme : toutes
            Description : Ce mot-clef permet de dire au compilateur que l’on veut que notre variable soit stockée de préférence dans un registre du processeur, au lieu de devoir être placée en mémoire RAM. C’est en effet le compilateur qui décide quelle variable stocker dans les registres, durant combien de temps, et à quel moment. On dit qu’ils se chargent d’allouer les registres. register permettait autrefois d’indiquer au compilateur que la variable désignée register était à placer (ou à copier) dans les registres dès que possible.

            L’utilité de register est très simple : un registre est au bas mot plus de 100 à 200 fois plus rapide que la mémoire RAM de notre ordinateur. Ainsi, placer (ou copier) une variable dans les registres permet d’accéder à celle-ci bien plus rapidement que si on devait la lire ou l’écrire depuis la mémoire RAM. Idéalement, on voudrait donc mettre toutes nos variables dans ces registres. Mais le problème, c’est que notre processeur ne possède que peu de registres. Il n’est ainsi pas rare d’avoir à se débrouiller avec seulement 4 à 8 registres. Autant dire qu’il faut alors réfléchir consciencieusement aux variables à placer dedans : il faut mettre de préférence des variables auxquelles on va accéder souvent (et ne pas hésiter à déplacer des variables entre registres et mémoire si besoin est). register permettait de préciser quelles étaient les variables à mettre en priorité dans les registres, histoire d’orienter le choix du compilateur. Cela permettait alors de rendre nos programmes plus rapides.

            Mais c’était il y a longtemps : de nos jours, register ne sert plus à rien (ou presque). La raison est très simple : les compilateurs actuels disposent d’algorithmes mathématiques qui permettent de gérer les registres de façon quasi optimale. En tout cas, nos compilateurs se débrouillent nettement mieux que les programmeurs pour décider quel registre utiliser et quelles données placer dedans. Ils n’ont donc plus besoin d’aide, et register est souvent ignoré ou sous-utilisé par ces compilateurs. En clair : register est une antiquité, qui ne doit plus être utilisé, et ne sert strictement à rien.
            • Partager sur Facebook
            • Partager sur Twitter
              2 janvier 2013 à 1:28:25

              Pour le sizeof ça serait bien de donner un exemple avec une structure et expliquer l'alignement.

              EDIT : Au fait, je pense que c'est un peu hors fonctionnement de sizeof car c'est le compilateur qui gère toussa.
              • Partager sur Facebook
              • Partager sur Twitter
                2 janvier 2013 à 12:14:05

                Je ne sais pas si c'est vraiment utile, mais tu pourrais préciser que size_t reste néanmoins un type non signé (donc ça ne risque pas d'être un int).

                Pour la partie sur register, je vais encore me faire crier dessus par Taurre, mais il y a une autre utilisation (qui relève sans doute du hack, du fait du mot-clé qui n'est alors plus très bien nommé), qui consiste à empêcher de prendre l'adresse d'une variable. Par rapport à une variable const par exemple, on a la certitude d'un diagnostic du compilateur. Pour le tuto, je comprends à peu près la conclusion, mais, sur le forum, on pourrait se permettre d'aller un peu plus loin que « Oulala, register c'est pour les viocs ». :-p
                • Partager sur Facebook
                • Partager sur Twitter
                Staff désormais retraité.
                Anonyme
                  2 janvier 2013 à 12:18:28

                  Citation : Lucas-84

                  Je ne sais pas si c'est vraiment utile, mais tu pourrais préciser que size_t reste néanmoins un type non signé (donc ça ne risque pas d'être un int).



                  Je pense que ça mérite d'être rajouté, je le fais.

                  Citation : Lucas-84


                  Pour la partie sur register, je vais encore me faire crier dessus par Taurre, mais il y a une autre utilisation (qui relève sans doute du hack, du fait du mot-clé qui n'est alors plus très bien nommé), qui consiste à empêcher de prendre l'adresse d'une variable. Par rapport à une variable const par exemple, on a la certitude d'un diagnostic du compilateur. Pour le tuto, je comprends à peu près la conclusion, mais, sur le forum, on pourrait se permettre d'aller un peu plus loin que « Oulala, register c'est pour les viocs ». :-p



                  D'ailleurs je n'ai jamais compris comment on pouvait avoir const et volatile dans la même déclaration. Je crois que la norme ne dit pas grand chose là-dessus.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 janvier 2013 à 12:28:32

                    Citation : informaticienzero

                    D'ailleurs je n'ai jamais compris comment on pouvait avoir const et volatile dans la même déclaration. Je crois que la norme ne dit pas grand chose là-dessus.


                    C'est moi ou le rapport logique est étrange (« d'ailleurs ») ? C'est autorisé, puisque les qualificateurs peuvent être combinés (en C99, on peut même utiliser plusieurs fois le même !). C'est utile, car ils ont deux principes différents. Quelle est ta question, en fait ?
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Staff désormais retraité.
                      2 janvier 2013 à 12:31:47

                      Citation : informaticienzero

                      D'ailleurs je n'ai jamais compris comment on pouvait avoir const et volatile dans la même déclaration. Je crois que la norme ne dit pas grand chose là-dessus.


                      Pour une variable qui ne doit pas être modifiée dans le programme, mais qui peut l'être par un thread extérieur, comme par exemple une variable contenant le timestamp, donc incrémentée automatiquement mais qui ne devrait pas pouvoir être modifiée par le programme.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        2 janvier 2013 à 13:38:26

                        C'est bon booti386 m'a expliqué un exemple concret. Je ne comprenais pas pourquoi une variable pouvait ne pas être modifiée par le programme mais pouvait l'être par un élément extérieur.

                        EDIT : ah oui mais non ! tu parlais de register. Je sais pas pourquoi j'ai lu volatile. Je devais pas être bien réveillé.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 janvier 2013 à 14:32:32

                          Sous gcc on peut forcer register à être un registre précis, j'avais découvert cela dans le code de qemu.

                          Par exemple :
                          int foo(void){return 42;}
                          int main(void){
                          register int eax asm("eax");
                          foo();
                          printf("%i\n",eax);
                          }
                          


                          Mais bon bien sur c'est pas du C standard. Le register de la norme n'est plus très utile, vu qu'avec les optimisations le compilateur peut déjà optimiser une variable en registre.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            2 janvier 2013 à 15:13:56

                            Génial, merci, j'en avais justement besoin pour optimiser un code, dans lequel toutes les variables rentrent dans tous les registres :)
                            • Partager sur Facebook
                            • Partager sur Twitter
                              2 janvier 2013 à 15:49:45

                              Toutes les variables ? o_O
                              T'en a combien ?
                              • Partager sur Facebook
                              • Partager sur Twitter
                                2 janvier 2013 à 16:08:51

                                En fait c'est pas exactement ça, dans le cadre du développement d'un mini-OS (64 bits), j'avais besoin de passer des paramètres à une fonction assembleur compilée séparément, donc je préfère utiliser des registres plutôt que la pile pour ça, et je n'ai aucune envie d'utiliser l'assembleur inline de GCC car je déteste la syntaxe AT&T, donc c'est un moyen de substitut pratique ^^
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Anonyme
                                  2 janvier 2013 à 18:34:13

                                  Citation : booti386

                                  En fait c'est pas exactement ça, dans le cadre du développement d'un mini-OS (64 bits), j'avais besoin de passer des paramètres à une fonction assembleur compilée séparément, donc je préfère utiliser des registres plutôt que la pile pour ça, et je n'ai aucune envie d'utiliser l'assembleur inline de GCC car je déteste la syntaxe AT&T, donc c'est un moyen de substitut pratique ^^



                                  Tu peux utiliser la syntaxe Intel avec l'assembleur inline de GCC (regarde ma bio pour plus d'informations).
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    2 janvier 2013 à 18:49:41

                                    Oui je sais, mais malheureusement il n'est pas possible d'utiliser les variables locales, donc ça me permettrait de copier directement les données qui m'intéressent dans les registres qui m'intéressent ^^^
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Anonyme
                                      2 janvier 2013 à 19:01:48

                                      Pourtant si chez moi ce code marche très bien :

                                      int main(void)
                                      {
                                          int a = 0;
                                          int b = 5;
                                      
                                          __asm__
                                          (
                                              ".intel_syntax noprefix\n\t"
                                              "mov eax, %1\n\t"
                                              "add eax, 5\n\t"
                                              "mov %0, eax\n\t"
                                              ".att_syntax"
                                                  :"=r"(a)
                                                  :"r"(b)
                                                  :"eax"
                                          );
                                      
                                          printf("a = %d\n", a);
                                      }
                                      
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Les mots clefs du C

                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                      • Editeur
                                      • Markdown