Discussion:Programmation C/Types de base

Dernier commentaire : il y a 15 ans par QLMT dans le sujet Entier

Entier

modifier

Constantes

modifier

Je suggère de retirer les exemples suivants du texte original (je les copie ici pour discussion):

unsigned long long max = ~ 0ULL; /* 18446744073709551615 si sizeof max == 8 */
long min = 1L << 31; /* -2147483648 si sizeof min == 4 */
  1. Ils me semblent un peu "trop tôt" dans le livre : les opérateurs binaires n'ont pas encore été vus !
  2. De plus, le deuxième exemple me semble invoquer un comportement indéfini : on décale une valeur positive, mais de type signée, d'un nombre de bits trop grand. Cf. 6.5.7p4 du n1124:
    The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

Des exemples de comportements indéfinis mériteraient d'être traités dans des chapitres plus avancés du cours, mais pas encore ici, je pense... On est censé n'en être encore qu'aux bases ! Alveric 5 juin 2006 à 15:18 (CEST)Répondre

Ah, voui, bonne remarque. Thierry Pierron 21 juin 2006 à 05:05 (CEST)Répondre

Domaines de Valeur

modifier

Je pense qu'une erreur s'est glissée en plusieurs endroits (6?) : dans les explications des représentations, il est écrit que sur N bits on peut coder (par exemple) des nombres de l'intervalle [-2^{N}-1;2^{N}-1], or il s'agit à chaque fois de {N-1} et non de {N}... QLMT 7 octobre 2009 à 18:20 (CEST)Répondre

Quelqu'un pour confirmer que l'en-tête stdint est apparu avec l'ISO C 99 ? Sinon quelqu'un sait ce qu'il en est de la définition d'un uint8_t sur une archie qui ne supporte pas les entiers 8bits ? Thierry Pierron 3 août 2006 à 15:45 (CEST)Répondre

Le rationale du C99 dit:
7.18 Integer types <stdint.h>
A new feature of C99.
De plus, le n1124 (C99 + TC1 + TC2 + quelques DR) dit:
7.18.1 Integer types
When typedef names differing only in the absence or presence of the initial u are defined, they shall denote corresponding signed and unsigned types as described in 6.2.5; an implementation providing one of these corresponding types shall also provide the other.
In the following descriptions, the symbol N represents an unsigned decimal integer with no leading zeros (e.g., 8 or 24, but not 04 or 048).
7.18.1.1 Exact-width integer types
The typedef name intN_t designates a signed integer type with width N, no padding bits, and a two’s complement representation. Thus, int8_t denotes a signed integer type with a width of exactly 8 bits.
The typedef name uintN_t designates an unsigned integer type with width N. Thus, uint24_t denotes an unsigned integer type with a width of exactly 24 bits.
These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two’s complement representation, it shall define the corresponding typedef names.
(Le n1124 a une marque en marge sur le dernier paragraphe, donc il y a dû avoir un changement dans les derniers DR...)
Donc ces types sont optionels, et une archi avec CHAR_BIT > 8 peut simplement ne pas définir [u]int8_t si elle ne le veut pas. De plus, j'y pense à l'instant, sizeof(int8_t) devant renvoyer un nombre entier, et les bits de bourrage étant interdits dans les types de taille fixe, je ne pense pas que ça puisse marcher...
Par ailleurs, tel que je le comprends, tu peux aussi avoir uint12_t, ou uint27_t. Ok, c'est très probablement inutile et sûrement compliqué à implémenter, mais c'est juste pour dire que la norme ne limite pas la liste à 8, 16, 32 et 64.
Si tu ne l'as pas déjà: cette page liste les docs ISO ou commentant l'ISO C90 et C99 (on pourrait la mettre en bibliographie du livre, note).
Par contre, concernant ta modif sur le tableau de valeurs, j'avais bien recopié ce qui est écrit dans les drafts. Je sais que c'est de l'ordre de l'archaïsme, mais la norme autorise le complément à 1 et le format « signe + magnitude » pour les entiers. Donc les bornes inférieures des types signés sont effectivement impaires, et d'où le -1 dans les formules du tableau... (arf, c'est piégeux à un point, ce langage... ;)
Alveric 3 août 2006 à 16:46 (CEST)Répondre
Bon, j'ai un peu remanié le texte. J'avoue que je n'étais pas trop sûr de mon coup là. Pour les valeurs, j'ai remis les anciennes. Je devais être mal réveillé quand j'ai fait les modifs, j'étais persuadé que -(2^16-1) = -65536 :-( Thierry Pierron 3 août 2006 à 21:55 (CEST)Répondre

Caractères

modifier

Trigraphes

modifier

Le paragraphe sur les trigraphes ne me semble pas à sa place dans ce chapitre: il ne s'agit pas d'une fonction propre au type caractère; je le mettrai plutôt dans le chapitre préprocesseur (ok, ce n'est pas une directive du préprocesseur, mais les trigraphes étant traités dans le tout début des phases de compilation, on peut les placer dans ce chapitre, je pense ?). D'autres idées ? Alveric 16 juin 2006 à 09:15 (CEST)Répondre

Bah, les trigraphes sont des caractères particuliers, mais comme c'est une fonctionnalité mal aimée et peu utilisée, le moins on en parle, le mieux ça vaudra. Pas la peine de bourrer le crâne sur des trucs obsolètes, à cause d'archis obsolètes, où pratiquement personne n'aura le malheur de coder dessus. Donc j'ai encore simplifié ton texte. Sorry. Thierry Pierron 21 juin 2006 à 05:04 (CEST)Répondre
"les trigraphes sont des caractères particuliers" -> oui et non... C'est une bidouille du niveau du préprocesseur plus que vraiment des caractères... Enfin.
Pas besoin d'être désolé. Je reconnais que je vais assez dans le détail ; par contre je pensais qu'il était intéressant de garder le passage sur les bogues possibles dûs aux trigraphes, au cas où quelqu'un tomberait dedans (c'est le genre de bogues rares, mais quand on tombe dessus, on est content d'avoir une doc sous la main). Mais cela a sûrement plus sa place dans un chapitre avancé que dans les premiers chapitres du livre (ça m'amène à une question que je pose dans la page de discussion principale). Alveric 21 juin 2006 à 15:56 (CEST)Répondre

Flottants

modifier
Par ailleurs, et il s'agit là d'un domaine très vaste qui dépasse le contexte de ce livre, les algorithmes de calcul numérique doivent être conçus de manière à éviter les accumulations d'erreurs infinitésimales (entre autres problèmes). Le code ci-dessus aurait ainsi pu être réécrit :

C'est vraiment le type de phrase que je déteste, particulièrement le "entre autres". Soit on enumère rapidement pour qu'on puisse gougler, soit on se tait. Hop, reformulation.

Par ailleurs dans l'exemple le suffixe F est inutile pour les constantes, puisqu'il y aura troncature à l'affectation. De toute façon les calculs en interne sont fait sur un type long double, quelque soit la façon d'écrire la constante, elle sera convertie en double, le F est donc complètement inutile. Thierry Pierron 3 août 2007 à 16:37 (CEST)Répondre

Je craint que GCC ne fasse la différence. Donc dire qu'il est inutile de mettre un "F" dépend surement du compilateur utilisé. En assembleur le type float (sous une autre forme) existe (x86-IA64) donc je pense qu'un compilateur moderne sait utiliser le float.P.Pignol

Des bornes inférieures

modifier

Dans le tableau concernant les entiers, les bornes inférieures sont de la formes 2X-1. Par exemple pour un char, les valeurs vont de -127 à +127 or on m'a toujours dit qu'un char était sur un octet.

Donc si je suis cette logique, un char peut prendre 256 valeurs : de 0 à 255 en unsigned et de -128 à +127 en signed.

Ceci dit je ne suis qu'un débutant en C et vous êtes sûrement expert en la matière. Je cherchais ici des précisions mais maintenant c'est un peu la pagaille dans ma tête.

Heureusement qu'on peut discuter sur le wiki !!

C'est tout à fait ça, étant donné que la plupart des architectures modernes utilise le complément à 2, les bornes inférieures des entiers signés sont bien de la forme -(2X). Le tableau est définit quel que soit l'architecture utilisée, comme par exemple le complément à 1 et signe+valeur absolue.
Signe+valeur absolue
un bit de signe, les autres bits = valeur absolue -> deux valeurs possibles pour 0 : +0 et -0.
Complément à 1
Quand un nombre est négatif, tous ses bits sont inversés. Encore deux valeurs possibles pour 0 : +0 (0000...0000) et -0 (1111...1111).
Le complément à 2 est maintenant l'architecture la plus répandue, car elle simplifie les algorithme de calcul, et 0 n'a qu'une valeur possible.
--DavidL 5 janvier 2008 à 15:15 (CET)Répondre
Revenir à la page « Programmation C/Types de base ».