CHAR_WIDTH no declarado

9

Recibo el error ‘CHAR_WIDTH’ undeclared cuando intento compilar este sencillo programa:

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

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

con

gcc ./show_char_width.c -o show_char_width

y gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) versión 8.3.0 (x86_64-linux-gnu) compilado por GNU C versión 8.3.0, GMP versión 6.1.2, MPFR versión 4.0.2, MPC versión 1.1.0 , versión isl isl-0.20-GMP, kernel: 5.0.0-37-generic.

Como se indica aquí, CHAR_WIDTH debe definirse en los límites. H, que se incluye en mi programa. Entonces, ¿por qué me sale este error?

Con la -vopción encontré que la biblioteca se buscará en esos directorios:

#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 contiene un limit.h que incluye syslimits.h desde el mismo directorio que a su vez incluye los siguientes límites.h, que según tengo entendido debería estar ubicado en el directorio / usr / include.

La macro CHAR_WIDTH está definida en esos archivos, pero en algunas condiciones que exceden mi conocimiento real.

Las condiciones que encontré hasta ahora son:


/* 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

y:

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

Por eso necesito tu ayuda.

Nota: obtengo el mismo error con todas las demás macros descritas en A.5.1, en particular: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH, etc.

pliski
fuente
¿Qué tipo de condiciones?
LPs
1
@LP: probablemente algunos que el PO no entiende -> " excede mi conocimiento real. "
alq
2
Después de la edición definirlo __STDC_WANT_IEC_60559_BFP_EXT__o pasarlo por línea de comando
LPs
1
FWIW, POSIX requiere CHAR_BITser 8, lo que debería significar CHAR_WIDTHque también debe ser 8 en los sistemas POSIX.
Andrew Henle
44
@pliski lo hiciste #defineantes de la #include?
LegendofPedro

Respuestas:

5

CHAR_WIDTHno es estándar, ni ninguna otra *_WIDTHmacro, pero el ancho de un tipo de caracteres debe ser el mismo que el de CHAR_BITtodos modos *.

En cuanto a las *_WIDTHmacros en general, no son estrictamente necesarias, ya que son computables en tiempo de compilación a partir del valor máximo del tipo sin signo correspondiente, es decir, puede tener un #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)que se expande a una expresión constante entera que también se puede usar en preprocesadores condicionales ( #if), aunque las implementaciones son un poco oscuras (consulte ¿Hay alguna forma de calcular el ancho de un tipo entero en tiempo de compilación? ), por ejemplo:

#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

Algunas personas simplemente lo hacen CHAR_BIT * sizeof(integer_type), pero eso no es estrictamente portátil , porque supone integer_typeque no tiene bits de relleno (generalmente no los tiene, pero en teoría puede tenerlos), y tampoco puede usarlo en #ifcondicionales.


* Desafortunadamente, para obtener esta información, debe saltar todo el estándar:

El ancho de un tipo entero se define (ligeramente indirectamente) como el número de sus bits sin relleno ( 6.2.6.2p6 ).

6.2.6.2p2 dice signed charque no tiene bits de relleno. Debido a cómo los números enteros se pueden representar en C ( 6.2.6.2p2 ), eso implica que unsigned chartampoco puede tener ningún bit de relleno, y dado que chardebe tener los mismos límites que uno signed charo unsigned char( 5.2.4.2.1p2 ) mientras tiene el mismo sizeofvalor ( a saber, 1, 6.5.3.4p4 ), un plano chartampoco puede tener bits de relleno, y por lo tanto CHAR_BIT == ancho de ( char| signed char| unsigned char) .

PSkocik
fuente