IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Programme compilé en 32 bits ou 64 bits


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    175
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 175
    Par défaut Programme compilé en 32 bits ou 64 bits
    Bonjour,

    Est-il possible de savoir depuis le code du programme, s'il a été compilé en 32 ou 64 bits ?

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par oranoutan
    Est-il possible de savoir depuis le code du programme, s'il a été compilé en 32 ou 64 bits ?
    Peut être. A quoi ça pourrait bien servir ?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    175
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 175
    Par défaut
    Il a des morceaux de code dans le code principal que j'aimerai par exemple exécutés uniquement sur des environements 32 ou 64 bits ...

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par oranoutan
    Il a des morceaux de code dans le code principal que j'aimerai par exemple exécutés uniquement sur des environements 32 ou 64 bits ...
    Du code 64 bit ne s'exécutera jamais sur une machine 32-bit. Ce genre de problème est réglé par la compilation conditionnelle. Il faut produire 2 exécutables (monappli32 et monappli64, à partir du même source) en changeant la définition des macros globales ad hoc.

  5. #5
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    Ce sont les options du compilateur qui définissent l'architecture sur laquelle va être portée le programme, mais en compilant pour amd64, la valeur renvoyée par sizeof devient un long unsigned int.
    La différence est dans l'adressage (8 octets au lieu de 4 octets) mais aussi dans la taille des différents types
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    TaillesEntiersAMD64.c :
    la taille d'un char est de 1 octets
    la taille d'un short est de 2 octets
    la taille d'un int est de 4 octets
    la taille d'un long int est de 8 octets
    la taille d'un long long int est de 8 octets
    la taille d'un float est de 4 octets
    la taille d'un double est de 8 octets
    la taille d'un long double est de 16 octets
    la taille d'un size_t est de 8 octets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    TailleEntiersi386.c:
    la taille d'un char est de 1 octets
    la taille d'un short est de 2 octets
    la taille d'un int est de 4 octets
    la taille d'un long int est de 4 octets
    la taille d'un long long int est de 8 octets
    la taille d'un float est de 4 octets
    la taille d'un double est de 8 octets
    la taille d'un long double est de 12 octets
    la taille d'un size_t est de 4 octets
    [EDIT](NB: je n'avais pas vu la réponse précédente. Est ce qui est entre [edit][/edit] correspond à ce que vous vouliez dire?)

    Il y a un problème par exemple dans les lignes du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("la taille d'un size_t est de %ld octets\n",sizeof(size_t));
    . (je ne saurai pas étendre la démonstration, pas assez de connaissance du C) si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o ./a.out  -pedantic -Wall -Wextra -march=k8 -mtune=i386 -m32  TailleEntiersAMD64.c
    , J'ai l'avertissement suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TailleEntiersAMD64.c:16: attention : format ‘%ld’ expects type ‘long int’, but argument 2 has type ‘unsigned int
    . Est-ce qu'il faudrait remplacer le type du format de sortie par une macro pour avoir un code portable et maintenable autrement que par la fonction "remplacer" des éditeurs de texte ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #if ARCH == AMD64
    #define SIZEOF_OUT "%ld"
    #elif ARCH == i386
    #define SIZEOF_OUT "%d"
    #endif
    Je crois qu'il faudrai écrire le programme avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("la taille d'un size_t est de SIZEOF_OUT octets\n",sizeof(size_t));
    pour éviter les erreurs de compilation et les warnings. Ça sûrement à voir avec le makefile et le ./configure, bien que je ne m'y connaisse pas trop.

    Ça donne sûrement une idée de ce qu'il ne faut pas faire pour écrire du code portable, mais c'est une question d'expert un peu. Je me demande par exemple si faire des casts est une bonne manière d'écrire un code portable.[/EDIT]

    On remarque que les tailles des types "simples" (short, char, int, float, double) ne changent pas, seulement celles des pointeurs et des types strictement calculatoires du genre long long int et long double (long double sur 128 bits pour AMD64 donc deux registres du processeur, contre long double sur 96 bits pour i386, ce qui fait 3*32 bits=trois registres processeurs). Ça donne une certaine idée des optimisations de calcul possibles avec le processeur AMD64.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o ./a.out  -pedantic -Wall -Wextra -march=i386 -m32
    signifie une compilation pour le jeu d'instructions i386 avec des instructions 32 bits
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o ./a.out  -pedantic -Wall -Wextra -march=k8 -m64
    signifie une compilation pour l'architecture k8 (AMD64) avec un jeu d'instructions 64 bits.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    175
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 175
    Par défaut
    Bonjour,

    merci à vous deux pour vos réponses.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #if ARCH == AMD64
    #define SIZEOF_OUT "%ld"
    #elif ARCH == i386
    #define SIZEOF_OUT "%d"
    #endif
    C'est quelque chose dans ce genre que je cherche mais je ne sais pas ou tu as trouvé le "ARCH", tu utilises quoi comme compilateur ? moi gcc.
    Je n'ai rien trouvé la dessus dans la doc.

    Mais cela m'a donné une idée dont voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char *arch;
     
    switch (sizeof(long int))
    {
    	default: arch="Inconnu"; break;
    	case 4: arch="x86/32bits"; break;
            case 8: arch="x86-64/64bits"; break;
    }
     
    printf("architecture utilisée : %s", arch);
    Si vous avez quelque chose de mieux n'hésitez pas, merci.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    salut pour la compilation conditionnelle, utilise l'option -D de gcc

    par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ARCH=LINUX
    gcc -Wall -W main.c -D$(ARCH) -o out

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par oranoutan
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #if ARCH == AMD64
    #define SIZEOF_OUT "%ld"
    #elif ARCH == i386
    #define SIZEOF_OUT "%d"
    #endif
    Grosse ânerie dectected.

    Le format dépend du type, c'est tout.

    Pour être tranquille, tu peux faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       printf ("%ld\n", (long) data);
    c'est portable et ça marche avec tous les types entiers signés de C90.

  9. #9
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    Donc le cast n'est pas proscrit ?

  10. #10
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par kromartien
    Donc le cast n'est pas proscrit ?
    Si on veut afficher un size_t en C90, je ne vois pas comment s'en passer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%lu", (unsigned long) sizeof(int))
    est la solution (note u et pas d, size_t est un type non signe). En C99 (et certains systemes le fournisse comme extension en C90), il y a "%zu" qui permet d'eviter le cast.

  11. #11
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par kromartien
    Donc le cast n'est pas proscrit ?
    Il y a des cas où il est recommandé, voire obligatoire. C'est le cas des fonctions variadics, parce que la promotion (cast automatique) n'est pas forcément celle qu'on pense.

    char -> int
    short -> int
    int -> int
    long -> long
    float -> double
    T * -> void *

  12. #12
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    quelles sont ces fonctions variadic pour la libc6 ?

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par kromartien
    quelles sont ces fonctions variadic pour la libc6 ?
    Les fonctions variadiques standards sont *printf et *scanf. Apres les systemes en ajoutent parfois (exemple: dans la famille des exec* sous unix, certaines sont variadiques).

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Il y a des cas où il est recommandé, voire obligatoire. C'est le cas des fonctions variadics, parce que la promotion automatique n'est pas forcément celle qu'on pense.
    Si la promotion automatique n'est pas celle que tu penses, il y a des risques que le cast n'aide pas parce que le resultat du cast va etre lui aussi promu.

  15. #15
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    la promotion automatique c'est le fait que de arguments float soient transformées en double à l'appel d'une fonction par exemple ?

  16. #16
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par kromartien
    la promotion automatique c'est le fait que de arguments float soient transformées en double à l'appel d'une fonction par exemple ?
    Oui, enfin promotion automatique, ça fait un peut redondant. 'promotion' suffit. (j'ai modifié mon post précédent).

  17. #17
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    dans quelle mesure alors faut-il utiliser les types double et int ? Est ce qu'il faut les privilégier à chaque fois, où pour les entiers par exemple, conaissant la gamme de variation, utiliser l'entier qui tient le moins de place ?

    (un char quand c'est possible, pour i allant de 1à 10 par exemple on prend i comme char, sinon un short, sinon un int ou bien systématiquement des int , et des long int en cas de besoin avéré)

  18. #18
    Membre émérite
    Avatar de SnakemaN
    Profil pro
    Bidouille-tout Android
    Inscrit en
    Juillet 2006
    Messages
    871
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Bidouille-tout Android

    Informations forums :
    Inscription : Juillet 2006
    Messages : 871
    Par défaut
    Pour ne revenir au sujet voici un bout d'un Makefile :
    CC = gcc

    CFLAGS = -O3 -march=i686 -finline-functions -Wall
    LDFLAGS = -s -lm ./shkComProcess.a

    GCC = gcc -Wall -pedantic -g -O3 -unroll
    etc....
    La partie en rouge précise l'architecture de compilation, par exemple la machine est un amd64 mais je "force" la compilation en 32bits pour la portabilité.
    D'ailleurs ca me vaut quelques soucis avec Valgrind qui est en 64bits et qui ne veut pas lancer cette appli....

    Donc par le Makefile on peut le savoir, même chose en utilisant Valgrind & co, mais depuis le source d'un programme, pour ma part rien n'est spécifié et vu que je n'utilise pas de champs de bit, je ne m'en soucis pas.

  19. #19
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par kromartien
    dans quelle mesure alors faut-il utiliser les types double et int ? Est ce qu'il faut les privilégier à chaque fois, où pour les entiers par exemple, conaissant la gamme de variation, utiliser l'entier qui tient le moins de place ?

    (un char quand c'est possible, pour i allant de 1à 10 par exemple on prend i comme char, sinon un short, sinon un int ou bien systématiquement des int , et des long int en cas de besoin avéré)
    Ce qui compte, ce n'est pas l'occupation mémoire, mais la simplicité. Les types char et short étant promus en int (même dans les expressions), il vaut mieux utiliser int directement, ça évite du code de promotion supplémentaire et inutile.

    Si int ne suffit pas, on utilise plus grand. Si les valeurs réelles sont requises (résolution < 1 : résultat de division, par exemple) on utilise double. Si le plage est insuffisante, on utilise long double.

    Les 2 types à privilégier sont donc :
    • Entiers : int
    • Réels : double

    Ca couvre 90% des besoins.

    Les types plus petits (signed char, short) sont utiles si on fait du stockage (gros tableaux). Jamais pour les paramètres, ni pour le calculs.

  20. #20
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    Oui mais l'architecture pour laquelle est compilée le programme n'est pas forcément la même pour chacun. Le programmeur ne va pas faire un source différent pour chaque architecture, c'est bien ça l'interêt d'avoir des sources.

    La portabilité demande de prendre en compte beaucoup d'architecture pour lesquelles le langage C ne défini pas les types calculatoire long double et long int de la même manière.

    le ./configure sert entre autre à déterminer l'architecture du processeur utilisé et à inscrire une variable ARCH dans le makefile je pense. Sous debian, la commande arch renvoie l'architecture du processeur.

    Mais modifier l'architecture cible de la compilation ne doit en rien modifier la sortie du compilateur, et c'est toute la difficulté quand certaines fonctions ne renvoient pas le même type en fonction de l'architecture cible passée à GCC. Le plus sûr serait encore de mettre i386 pour tout le monde, mais les processeurs ont évolué depuis. Il faut également que les programmes marchent pour i386 aussi. Alors que faire ? mettre dans un source "Ce programme n'est pas exécutable sur i386" bien que gcc permette de le compiler pour i386

    Faire un source portable sur toutes les architectures demande en tout cas une bonne connaissance du C.

    Le cast (étendre la valeur à un type plus large) est une solution, mais ce n'est pas non plus optimal. D'un autre côté, écrire les programmes en assembleur non plus. Alors Pas facile de savoir ce qu'il faut faire pour que le programme soit vraiment optimisé en fonction du processeur tout en gardant un source portable à l'extrême.

Discussions similaires

  1. Faire tourner un programme 32 bits sous 64 bits
    Par rambc dans le forum Débuter
    Réponses: 7
    Dernier message: 01/03/2013, 00h32
  2. programme avec instruction MOVE et décalage de bit.
    Par jerdel dans le forum Automation
    Réponses: 4
    Dernier message: 17/01/2012, 14h38
  3. Réponses: 0
    Dernier message: 07/04/2011, 14h38
  4. [COMPILER] [MEX] compiler du C sous Vista 64 bits
    Par S4sha dans le forum MATLAB
    Réponses: 11
    Dernier message: 29/02/2008, 21h04
  5. compilation 64 bits sur 32 bits
    Par YéTeeh dans le forum C++
    Réponses: 8
    Dernier message: 05/01/2008, 17h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo