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 -v
opçã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.
__STDC_WANT_IEC_60559_BFP_EXT__
ou passá-lo pela linha de comandoCHAR_BIT
8, o que significaCHAR_WIDTH
que também deve ser 8 em sistemas POSIX.#define
antes do#include
?Respostas:
CHAR_WIDTH
não é padrão nem outras*_WIDTH
macros, mas a largura de um tipo de caractere deve ser a mesmaCHAR_BIT
*.Quanto às
*_WIDTH
macros 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:Algumas pessoas simplesmente o fazem
CHAR_BIT * sizeof(integer_type)
, mas isso não é estritamente portátil , porque assumeinteger_type
que não possui bits de preenchimento (normalmente não possui, mas teoricamente pode obtê-los) e também não pode usá-lo em#if
condicionais.* 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 char
que 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 queunsigned char
também não pode ter nenhum bit de preenchimento e, poischar
deve ter os mesmos limites que ( 5.2.4.2.1p2 )signed char
ou 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 char
sizeof
char
CHAR_BIT
char
signed char
unsigned char
fonte