CHAR_WIDTH não declarado


9

Eu recebo o erro ‘CHAR_WIDTH’ undeclared quando tento compilar este programa simples:

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

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

com

gcc ./show_char_width.c -o show_char_width

e gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) versão 8.3.0 (x86_64-linux-gnu) compilado pelo GNU C versão 8.3.0, GMP versão 6.1.2, MPFR versão 4.0.2, MPC versão 4.0.2, MPC versão 1.1.0 , versão isl isl-0.20-GMP, kernel: 5.0.0-37-generic.

Conforme indicado aqui, CHAR_WIDTH deve ser definido em limits.h, que está incluído no meu programa. Então, por que eu recebo esse erro?

Com a -vopção, descobri que a biblioteca será pesquisada nesses diretórios:

#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 contém um limite.h que inclui syslimits.h do mesmo diretório que por sua vez inclui os próximos limites.h, que, pelo que entendi, devem estar localizados em o diretório / usr / include.

A macro CHAR_WIDTH é realmente definida nesses arquivos, mas sob algumas condições que excedem meu conhecimento real.

As condições que encontrei até agora são:


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

e:

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

Por isso preciso da sua ajuda.

Nota: Recebo o mesmo erro com todas as outras macros descritas em A.5.1, nomeadamente: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH, etc.


Que tipo de condições?
LPs

11
@LP: provavelmente alguns que o OP não entende -> " excedem meu conhecimento real " .
alk

2
Após a edição. definir __STDC_WANT_IEC_60559_BFP_EXT__ou passá-lo pela linha de comando
LPs

11
FWIW, POSIX requer CHAR_BIT8, o que significa CHAR_WIDTHque também deve ser 8 em sistemas POSIX.
Andrew Henle

4
@pliski você fez #defineantes do #include?
LegendofPedro 6/12/19

Respostas:


5

CHAR_WIDTHnão é padrão nem outras *_WIDTHmacros, mas a largura de um tipo de caractere deve ser a mesma CHAR_BIT*.

Quanto às *_WIDTHmacros em geral, elas não são estritamente necessárias, pois são computáveis ​​em tempo de compilação a partir do valor máximo do tipo não assinado correspondente, ou seja, você pode ter uma #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)que se expanda para uma expressão constante inteira que também pode ser usada em condicionais do pré-processador ( #if), embora as implementações sejam um pouco obscuras (consulte Existe alguma maneira de calcular a largura de um tipo inteiro no tempo de compilação? ), por exemplo:

#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

Algumas pessoas simplesmente o fazem CHAR_BIT * sizeof(integer_type), mas isso não é estritamente portátil , porque assume integer_typeque não possui bits de preenchimento (normalmente não possui, mas teoricamente pode obtê-los) e também não pode usá-lo em #ifcondicionais.


* Infelizmente, para recolher essas informações, você precisa pular todo o padrão:

A largura de um tipo inteiro é (um pouco indiretamente) definida como o número de seus bits sem preenchimento ( 6.2.6.2p6 ).

6.2.6.2p2 diz signed charque não possui nenhum bit de preenchimento. Por causa de como os números inteiros podem ser representados em C ( 6.2.6.2p2 ), isso implica que unsigned chartambém não pode ter nenhum bit de preenchimento e, pois chardeve ter os mesmos limites que ( 5.2.4.2.1p2 ) signed charou com o mesmo valor ( 5.2.4.2.1p2 ) . ou seja, 1, 6.5.3.4p4 ), uma planície também não pode ter bits de preenchimento e, portanto, == largura de ( | | ) .unsigned charsizeofcharCHAR_BIT charsigned charunsigned char

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.