OVH Cloud OVH Cloud

Taille d'un char en C

33 réponses
Avatar
Jean
Bonjour,

Il me semblait avoir lu sur ce NG que la taille
d'un char en C valait 1 (sans autre précision sur l'unité) et
que cette taille pouvait être 7, 8 ou plus bits.
J'ai téléchargé la norme ISO/IEC 9899:1999 du langage C
mais je n'ai rien trouvé sur cela.
Pour ceux qui auraient également la norme, pouvez-vous
me dire à quel paragraphe je peux trouver cette info ?
Merci d'avance.
Jean

10 réponses

1 2 3 4
Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Nicolas Favre-Félix"
wrote:

Je dois admettre mon erreur, cela me semblait tellement gros que j'ai eu
beaucoup de mal à y croire.


Ok.

En tout cas l'un des axiome du C est : sizeof(char) == 1 retourne
toujours
vrai.

Alors comment le PDP-10 fait-il?
( http://pdp10.nocrew.org/gcc/ )
Il possède un <<"71-bit" double-precision integer format >>


Et?

Mais alors quelle est le résultat renvoyé par sizeof avec ce type comm
paramètre, car un char fait 9 bits sur cette machine? Si la fonction


On vient de te le dire : sizeof(char) renvoi 1 quelque soit la machine. Le
char est la plus petite unité adressable >= 8 bits d'une architecture donnée.

renvoie 8, alors un bit est en trop. Si sizeof se base sur le char pour
déterminer son unité, comment cette fonction fait-elle si le nombre de
bits d'un type/le nombre de bits du type char n'est pas un entier?


Quoi, des demi bits? Faut arréter de fumer les fils de bananes, ça grille les
neurones...

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Couic" <@> wrote:

Citez moi UNE SEULE plateforme qui a des chars de plus de 8 bits.


Texas TMS320C54 : 16-bit
Motorola 56156 : 32-bit


question 1 :
puisque la taille d'un char peut varier
d'une machine à l'autre et donc la taille de tous
les autres types aussi, comment un pgm C standard
peut-il rester portable d'une machine à l'autre ?


En suivant scrupuleusement les consignes, c'est à dire les valeurs minimales
garanties, à savoir:

char 8-bit
int 16-bit
long 32-bit
long long 64-bit (C99)

(en fait on doit plutôt s'intéresser aux gammes de valeurs minimales,
127..+127, 0-255 etc.)

Par exemple, les programmes faisant l'hypothèse que int fait 32-bit ne sont
pas portables.

question 2 :
si j'écris un pgm C strictement standard avec
mon EDI sur une machine d'architecture X,
je pourrai prendre l'exécutable généré et aussitôt
le faire tourner sur une machine d'architecture Y ou bien


Non. La portabilité est assurée au niveau source. (C != Java)

s'il est impératif de le recompiler sur la nouvelle machine?


Oui.

Je ne comprends pas bien comment tout cela "s'imbrique" :-((
Si qq'un a une adresse web sur "comment interagit le compilateur
avec la machine" ça serait super.


C'est assez simple.

Tout commence par des fichiers textes qui sont

Les fichiers sources (.c)
Les fichiers d'entête (.h)

Ensuite, on appelle le compilateur qui va transformer ces fichiers sources en
fichiers 'objets' (.o, .obj...)

En gros (les détails appartiennent à chaque implémentation) un fichier objet
contient du code machine résultant de la compilation. Il n'est probablement
pas directement exécutable, car il est probable qu'il y ait des adresses non
resolues (références à des objets ou à des fonctions externes au module).

En va ensuite appeler l'éditeur de lien (liker) qui va prendre en compte
l'ensemble des fichiers objets, et qui va tenter d'en faire un fichier
executable dans lequel les liens seront résolus. Pour cela il aura peut être
besoin de quelques compléments contenus dans des bibliothèques (.a, .lib)
comme la bibliothèque standard d'exécution du C (RTL) ou des extensions
standard (Math library), ou des extensions non standard (sockets, threads,
GUI etc.)

Le résultat devrait être un fichier exécutable (., .x, .exe etc.)

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/



Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Benoit Dejean wrote:

mais bordel, qui a inventé cette pseudo-abréviation "pgm" ???


Voilà une remarque intéressante et constructive...

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Bertrand Mollinier Toublet
Emmanuel Delahaye wrote:
In 'fr.comp.lang.c', "Couic" <@> wrote:


Citez moi UNE SEULE plateforme qui a des chars de plus de 8 bits.


Texas TMS320C54 : 16-bit
Motorola 56156 : 32-bit


question 1 :
puisque la taille d'un char peut varier
d'une machine à l'autre et donc la taille de tous
les autres types aussi, comment un pgm C standard
peut-il rester portable d'une machine à l'autre ?



En suivant scrupuleusement les consignes, c'est à dire les valeurs minimales
garanties, à savoir:

char 8-bit
int 16-bit
long 32-bit
long long 64-bit (C99)

(en fait on doit plutôt s'intéresser aux gammes de valeurs minimales,
127..+127, 0-255 etc.)

Par exemple, les programmes faisant l'hypothèse que int fait 32-bit ne sont
pas portables.


question 2 :
si j'écris un pgm C strictement standard avec
mon EDI sur une machine d'architecture X,
je pourrai prendre l'exécutable généré et aussitôt
le faire tourner sur une machine d'architecture Y ou bien



Non. La portabilité est assurée au niveau source. (C != Java)


s'il est impératif de le recompiler sur la nouvelle machine?



Oui.


Je ne comprends pas bien comment tout cela "s'imbrique" :-((
Si qq'un a une adresse web sur "comment interagit le compilateur
avec la machine" ça serait super.



C'est assez simple.

Tout commence par des fichiers textes qui sont

Les fichiers sources (.c)
Les fichiers d'entête (.h)

Ensuite, on appelle le compilateur qui va transformer ces fichiers sources en
fichiers 'objets' (.o, .obj...)

En gros (les détails appartiennent à chaque implémentation) un fichier objet
contient du code machine résultant de la compilation. Il n'est probablement
pas directement exécutable, car il est probable qu'il y ait des adresses non
resolues (références à des objets ou à des fonctions externes au module).

En va ensuite appeler l'éditeur de lien (liker) qui va prendre en compte
l'ensemble des fichiers objets, et qui va tenter d'en faire un fichier
executable dans lequel les liens seront résolus. Pour cela il aura peut être
besoin de quelques compléments contenus dans des bibliothèques (.a, .lib)
comme la bibliothèque standard d'exécution du C (RTL) ou des extensions
standard (Math library), ou des extensions non standard (sockets, threads,
GUI etc.)

Le résultat devrait être un fichier exécutable (., .x, .exe etc.)

Puisqu'on rentre dans les details hors de nos frontieres, tu oublies

d'ajouter que le fichier executable n'est probablement pas une image
exacte d'un code executable, mais qu'au moment de l'execution, un loader
se charge de le placer quelque part en memoire, de faire les derniers
re-arrangement quant a l'emplacement du code et des donnees (sur les
machines sur lesquelles la distinction est faire) et de mettre a jour
les addresses une derniere fois.

--
Bertrand Mollinier Toublet
"Reality exists" - Richard Heathfield, 1 July 2003




Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Bertrand Mollinier Toublet
wrote:

Puisqu'on rentre dans les details hors de nos frontieres, tu oublies
d'ajouter que le fichier executable n'est probablement pas une image
exacte d'un code executable, mais qu'au moment de l'execution, un loader
se charge de le placer quelque part en memoire, de faire les derniers
re-arrangement quant a l'emplacement du code et des donnees (sur les
machines sur lesquelles la distinction est faire) et de mettre a jour
les addresses une derniere fois.


Exact. J'ai trop l'habitude de travailler en embarqué!

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Fabien KOCIK
"Couic" <@> a écrit dans le message news:
3f0fee4a$0$10887$
Citez moi UNE SEULE plateforme qui a des chars de plus de 8 bits.


Texas TMS320C54 : 16-bit
Motorola 56156 : 32-bit


salut,

question 2 :
si j'écris un pgm C strictement standard avec
mon EDI sur une machine d'architecture X,
je pourrai prendre l'exécutable généré et aussitôt
le faire tourner sur une machine d'architecture Y ou bien
s'il est impératif de le recompiler sur la nouvelle machine?


Il faut recompiler sur la machine Y, ce qui est portable en C,
c'est le source.
Si tu veux porter des exécutables directement, il faut utiliser
ce que l'on appèle une machine virtuelle, c'est à dire une couche
logicielle qui émule un processeur dont la spéccification est standardisée
et qui a été compilée sur plusieurs plateformes différentes.
Plusieurs langages offrent cette possibilité (JAVA, le plus connu, mais
aussi COBOL ou EIFFEL...).

Je ne comprends pas bien comment tout cela "s'imbrique" :-((
Si qq'un a une adresse web sur "comment interagit le compilateur
avec la machine" ça serait super.
Couic



Le compilo est un programme qui "traduit" (il optimise aussi) le code
source C en un code binaire directement interprétable par la machine.
Chaque plateforme dispose d'un compilateur qui est rédigé dans le langage
qu'elle supporte.

@+ Fabien



Avatar
Antoine Leca
Couic écrivit
Tout d'abord je débute en C et j'ai 2 questions :
question 1 :
puisque la taille d'un char peut varier
d'une machine à l'autre et donc la taille de tous
les autres types aussi, comment un pgm C standard
peut-il rester portable d'une machine à l'autre ?


En évitant de penser en terme de solution (la taille des types,
comme l'on fait en langage d'assemblage) et en pensant plutôt
en termes d'algorithme, ou comment résoudre les problèmes.

La seule chose qu'il *faut* savoir, c'est l'étendue
garantie des types (pour les entiers). Et le problème actuel
du C, c'est que int ne garantit que ±32700, ce qui est
insuffisant pour certains problèmes; mais utiliser des longs
devient idiots avec les machines hybrides 32/64 bits, où
les longs sont sur 64 bits, avec une dégradation sensible des
performances par rapport aux ints sur 32 bits (c'est
probablement pour cela que M$ a décidé que LONG=2 bits).
Ma solution actuellement est de définir un type (que nous
baptisons habituellement Int pour faciliter la lecture) qui
est comme int, sauf qu'il garantit 32 bits. Sa définition est

#if MAX_INT-0 < 2147483647
typedef long Int;
#else
typedef int Int;
#endif

Donne pleinement satisfaction.

Bien entendu, il y a des morceaux de programmes qui ont absolument
besoin de manipuler des objets de taille précise. La solution
"initiale" du C était les champs de bits, mais ce n'était ni pratique
ni fonctionnel (trop de bogues). Actuellement, on a donc un kyrielle
de types avec des tailles bien définies; l'absence de normalisation
a fait qu'il existe plusieurs séries de noms pour ces objets, qui
varient en fonction des goûts, des couleurs, de la marque du S.E.
et du bouquin où on a appris à programmer. Bon, la chose à retenir,
c'est que ces choses-là devraient être bannies de tous les programmes
C qui n'ont pas *absolument* besoin de manipuler des objets de taille
fixée. Et SURTOUT PAS être utilisé pour résoudre le problème que
j'ai exposé précédement : parce que le jour où il faudra porter le
programme sur une machine 64 ou 128 bits, on va être bien embêté avec
toutes les variables déclarées u32_t...


Antoine

Avatar
Richard Delorme
Antoine Leca wrote:

La seule chose qu'il *faut* savoir, c'est l'étendue
garantie des types (pour les entiers). Et le problème actuel
du C, c'est que int ne garantit que ±32700, ce qui est
insuffisant pour certains problèmes; mais utiliser des longs
devient idiots avec les machines hybrides 32/64 bits, où
les longs sont sur 64 bits, avec une dégradation sensible des
performances par rapport aux ints sur 32 bits (c'est
probablement pour cela que M$ a décidé que LONG=2 bits).


Les machines sur lesquelles les long sont codés sur 64 bits, calculent aussi
vite sur 64 bits que sur 32. Le seul problème de performance est la
consommation de bande-passante, mais ce n'est pas le problème principal de
performance des processeurs d'aujourd'hui.

Ma solution actuellement est de définir un type (que nous
baptisons habituellement Int pour faciliter la lecture) qui
est comme int, sauf qu'il garantit 32 bits. Sa définition est

#if MAX_INT-0 < 2147483647
typedef long Int;
#else
typedef int Int;
#endif

Donne pleinement satisfaction.


Mauvaise idée à mon avis. L'erreur de frappe <i>nt au lieu de <I>nt à toute
les chances de passer inaperçu, sauf, loi de Murphy oblige, au moment où il
ne faut pas.

Bien entendu, il y a des morceaux de programmes qui ont absolument
besoin de manipuler des objets de taille précise. La solution
"initiale" du C était les champs de bits, mais ce n'était ni pratique
ni fonctionnel (trop de bogues). Actuellement, on a donc un kyrielle
de types avec des tailles bien définies; l'absence de normalisation


Quelle absence de normalisation ? <stdint.h> n'est pas standard ?

a fait qu'il existe plusieurs séries de noms pour ces objets, qui
varient en fonction des goûts, des couleurs, de la marque du S.E.
et du bouquin où on a appris à programmer. Bon, la chose à retenir,
c'est que ces choses-là devraient être bannies de tous les programmes
C qui n'ont pas *absolument* besoin de manipuler des objets de taille
fixée. Et SURTOUT PAS être utilisé pour résoudre le problème que
j'ai exposé précédement : parce que le jour où il faudra porter le
programme sur une machine 64 ou 128 bits, on va être bien embêté avec
toutes les variables déclarées u32_t...


Le type int32_t est standard (norme C99), quoique non requis par la norme
(sans doute pour ne pas embêter les systèmes tordus à 24 ou 36 bits).

--
Richard

Avatar
Bertrand Mollinier Toublet
Couic wrote:
Il faut recompiler sur la machine Y, ce qui est portable en C,
c'est le source.


Mais tous les codes sources de tous les
langages ne sont donc pas portable ??



Pas necessairement. Meme du code source pour du C n'est pas
necessairement portable. Exemple:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int c = 1 << 17;
printf("%dn", c);
return EXIT_SUCCESS;
}

Sur mon PC, les int font 32 bits (31 de valeur, 1 de signe). Le code
ci-dessus, compile pour ma plateforme est donc parfaitement correct et a
pour sortie:

131072

Maintenant, il se trouve que la norme ne garantit qu'une plage de -32767
a +32767 pour les int. Il existe certainement des architectures, sur
lesquelles ces limitations sont en vigueur. Sur une telle architecture,
la premiere ligne du programme resulte en un debordement pour une valeur
signee, ce qui est un comportement indefini selon la norme.

Le code n'est donc pas portable: son comportement est different sur deux
architectures differentes.

Le compilo est un programme qui "traduit" (il optimise aussi) le code
source C en un code binaire directement interprétable par la machine.
Chaque plateforme dispose d'un compilateur qui est rédigé dans le langage
qu'elle supporte.



Ca veut donc dire que, sur une machine donnée,
c'est le compilateur qui, au moment de faire son travail,
va "voir" dans le processeur (ou ailleurs ??) combien de bits
celui-ci utilise pour traiter 1 caractère??


Pas exactement, non. Le compilateur a ete cree pour une architecture
donnee. Il connait (parce que son createur les lui a enseignees) les
caracteristiques de la plateforme sur laquelle il travaille.

--
Bertrand Mollinier Toublet
"Reality exists" - Richard Heathfield, 1 July 2003


Avatar
Horst Kraemer
On Wed, 16 Jul 2003 09:06:45 -0700, Bertrand Mollinier Toublet
wrote:

Sur mon PC, les int font 32 bits (31 de valeur, 1 de signe).


Donc 10000000 00000000 00000000 00000001 vaut -1 ?

Quel PC ?

--
Horst

1 2 3 4