CHAR_WIDTH niezadeklarowany

9

‘CHAR_WIDTH’ undeclared Podczas próby skompilowania tego prostego programu pojawia się błąd :

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

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

z

gcc ./show_char_width.c -o show_char_width

i gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) wersja 8.3.0 (x86_64-linux-gnu) skompilowana przez GNU C wersja 8.3.0, GMP wersja 6.1.2, MPFR wersja 4.0.2, MPC wersja 1.1.0 , wersja isl isl-0.20-GMP, jądro: 5.0.0-37-generic.

Jak wspomniano tutaj CHAR_WIDTH należy zdefiniować w limit.h, który jest zawarty w moim programie. Dlaczego więc otrzymuję ten błąd?

Z -vopcją stwierdziłem, że biblioteka będzie przeszukiwana w tych katalogach:

#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 zawiera limit.h, który obejmuje syslimits.h z tego samego katalogu, który z kolei zawiera kolejne limity.h, który z mojego zrozumienia powinien znajdować się w katalog / usr / include.

Makro CHAR_WIDTH jest rzeczywiście zdefiniowane w tych plikach, ale pod pewnymi warunkami, które przekraczają moją rzeczywistą wiedzę.

Warunki, które do tej pory znalazłem to:


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

i :

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

Dlatego potrzebuję twojej pomocy.

Uwaga: pojawia się ten sam błąd ze wszystkimi innymi makrami opisanymi w A.5.1, w szczególności: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH itp.

pliski
źródło
Jakie warunki?
LP
1
@LP: prawdopodobnie niektórzy, których OP nie rozumie -> „ przekraczają moją rzeczywistą wiedzę.
alk
2
Po edycji. zdefiniuj __STDC_WANT_IEC_60559_BFP_EXT__lub przekaż to wierszem poleceń
LP
1
FWIW, POSIX wymaga CHAR_BIT8, co oznacza, że CHAR_WIDTHmusi być również 8 w systemach POSIX.
Andrew Henle,
4
@pliski czy #definewcześniej #include?
LegendofPedro,

Odpowiedzi:

5

CHAR_WIDTHnie jest standardem, podobnie jak inne *_WIDTHmakra, ale szerokość typu znaku musi być taka sama jak w CHAR_BITkażdym przypadku *.

Jeśli chodzi o *_WIDTHmakra, nie są one absolutnie potrzebne, ponieważ można je obliczyć w czasie kompilacji z maksymalnej wartości odpowiedniego typu bez znaku, tzn. Możesz mieć ciąg #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)rozwijany do wyrażenia stałego liczb całkowitych, które można również stosować w warunkach warunkowych preprocesora ( #if), chociaż implementacje są nieco niejasne (patrz Czy jest jakiś sposób na obliczenie szerokości typu liczby całkowitej w czasie kompilacji? ), np .:

#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

Niektóre osoby tak robią CHAR_BIT * sizeof(integer_type), ale to nie jest przenośne , ponieważ zakłada, integer_typeże nie ma bitów wypełniających (zwykle nie, ale teoretycznie może je mieć) i nie może używać go również w #ifwarunkowym.


* Niestety, aby zebrać te informacje, musisz przeskoczyć cały standard:

Szerokość typu liczb całkowitych jest (nieco pośrednio) zdefiniowana jako liczba bitów niepochodzących ( 6.2.6.2p6 ).

6.2.6.2p2 mówi, signed charże nie ma żadnych bitów wypełniających. Ze względu na to, w jaki sposób liczby całkowite mogą być reprezentowane w C ( 6.2.6.2p2 ), oznacza to, że unsigned charnie mogą mieć również żadnych bitów wypełniających, a ponieważ charmuszą mieć takie same ograniczenia jak jeden signed charlub unsigned char( 5.2.4.2.1p2 ), a jednocześnie mieć tę samą sizeofwartość ( mianowicie 1, 6.5.3.4p4 ), zwykły charnie może mieć także żadnych bitów dopełniających, a więc CHAR_BIT == szerokość ( char| signed char| unsigned char) .

PSkocik
źródło