CHAR_WIDTH non déclaré

9

J'obtiens l'erreur ‘CHAR_WIDTH’ undeclared lorsque j'essaie de compiler ce programme simple:

#include <stdio.h>
#include <limits.h>

int main()
{
  printf("CHAR_BIT = %d\n", CHAR_BIT);
  printf("CHAR_WIDTH = %d\n", CHAR_WIDTH);
  return (0);
}

avec

gcc ./show_char_width.c -o show_char_width

et gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) version 8.3.0 (x86_64-linux-gnu) compilé par GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0 , version isl isl-0.20-GMP, noyau: 5.0.0-37-générique.

Comme indiqué ici, CHAR_WIDTH doit être défini dans limits.h qui est inclus dans mon programme. Alors pourquoi j'ai cette erreur?

Avec l' -voption, j'ai trouvé que la bibliothèque sera recherchée dans ces répertoires:

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

/ usr / lib / gcc / x86_64-linux-gnu / 8 / include-fixed contient un limits.h qui inclut syslimits.h du même répertoire qui à son tour inclut le prochain limits.h, qui d'après ma compréhension devrait se trouver dans le répertoire / usr / include.

La macro CHAR_WIDTH est en effet définie dans ces fichiers mais sous certaines conditions qui dépassent mes connaissances réelles.

Les conditions que j'ai trouvées jusqu'à présent sont les suivantes:


/* The integer width macros are not defined by GCC's <limits.h> before
   GCC 7, or if _GNU_SOURCE rather than
   __STDC_WANT_IEC_60559_BFP_EXT__ is used to enable this feature.  */
#if __GLIBC_USE (IEC_60559_BFP_EXT)
# ifndef CHAR_WIDTH
#  define CHAR_WIDTH 8
# endif

et :

#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
/* TS 18661-1 widths of integer types.  */
# undef CHAR_WIDTH
# define CHAR_WIDTH __SCHAR_WIDTH__

Voilà pourquoi j'ai besoin de votre aide.

Remarque: j'obtiens la même erreur avec toutes les autres macros décrites en A.5.1 notamment: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH, etc.

pliski
la source
Quel genre de conditions?
LPs
1
@LP: probablement certains que le PO ne comprend pas -> " dépasser mes connaissances réelles. "
alk
2
Après l'édition. définir __STDC_WANT_IEC_60559_BFP_EXT__ou passer par ligne de commande
LPs
1
FWIW, POSIX doit CHAR_BITêtre 8, ce qui devrait signifier qu'il CHAR_WIDTHdoit également être 8 sur les systèmes POSIX.
Andrew Henle
4
@pliski l'aviez-vous #defineavant le #include?
LegendofPedro

Réponses:

5

CHAR_WIDTHn'est pas standard, ni aucune autre *_WIDTHmacro, mais la largeur d'un type de caractère doit être la même que de CHAR_BITtoute façon *.

Quant aux *_WIDTHmacros en général, elles ne sont pas strictement nécessaires car elles sont calculables au moment de la compilation à partir de la valeur maximale du type non signé correspondant, c'est-à-dire que vous pouvez avoir un #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)qui se développe en une expression constante entière qui est également utilisable dans les conditions préalables du préprocesseur ( #if), bien que les implémentations soient un peu obscures (voir Existe - t-il un moyen de calculer la largeur d'un type entier au moment de la compilation? ), par exemple:

#define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax) POW2_MINUS1_BITS_2039(UnsignedMax)
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define POW2_MINUS1_BITS_2039(X) ((X)/((X)%255+1) / 255%255*8 + 7-86/((X)%255+12))

//compile-time test it, assuming uint{8,16,32,64}_t exist
#include <inttypes.h>
#if WIDTH_FROM_UNSIGNED_MAX(UINT8_MAX) != 8
    #error
#endif
#if WIDTH_FROM_UNSIGNED_MAX(UINT16_MAX) != 16
    #error
#endif
#if WIDTH_FROM_UNSIGNED_MAX(UINT32_MAX) != 32
    #error
#endif
#if WIDTH_FROM_UNSIGNED_MAX(UINT64_MAX) != 64
    #error
#endif

Certaines personnes le font CHAR_BIT * sizeof(integer_type), mais ce n'est pas strictement portable , car il suppose qu'il integer_typen'a pas de bits de remplissage (il n'en a généralement pas mais théoriquement il peut les avoir), et ne peut pas non plus l'utiliser dans des #ifconditions.


* Malheureusement, pour glaner ces informations, vous devez sauter partout dans la norme:

La largeur d'un type entier est (légèrement indirectement) définie comme le nombre de ses bits non remplis ( 6.2.6.2p6 ).

6.2.6.2p2 dit qu'il signed charn'a pas de bits de remplissage. En raison de la façon dont les entiers peuvent être représentés en C ( 6.2.6.2p2 ), cela implique qu'ils unsigned charne peuvent pas non plus avoir de bits de remplissage, et qu'ils chardoivent avoir les mêmes limites que l'un signed charou l' autre unsigned char( 5.2.4.2.1p2 ) tout en ayant la même sizeofvaleur ( à savoir 1, 6.5.3.4p4 ), une plaine charne peut pas non plus avoir de bits de remplissage, et donc CHAR_BIT == largeur de ( char| signed char| unsigned char) .

PSkocik
la source