CHAR_WIDTH non dichiarato


9

Ottengo l'errore ‘CHAR_WIDTH’ undeclared quando provo a compilare questo semplice programma:

#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

e gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) versione 8.3.0 (x86_64-linux-gnu) compilata da GNU C versione 8.3.0, GMP versione 6.1.2, MPFR versione 4.0.2, MPC versione 1.1.0 , versione isl isl-0.20-GMP, kernel: 5.0.0-37-generico.

Come indicato qui, CHAR_WIDTH dovrebbe essere definito in limits.h che è incluso nel mio programma. Quindi perché ottengo questo errore?

Con l' -vopzione ho scoperto che la libreria verrà cercata in quelle directory:

#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 contengono un limite.h che include syslimits.h dalla stessa directory che a sua volta include i limiti successivi.h, che dalla mia comprensione dovrebbe trovarsi in la directory / usr / include.

La macro CHAR_WIDTH è infatti definita in quei file ma in alcune condizioni che superano le mie attuali conoscenze.

Le condizioni che ho trovato fino ad ora sono:


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

Ecco perché ho bisogno del tuo aiuto.

Nota: ottengo lo stesso errore con tutte le altre macro descritte in A.5.1, in particolare: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH, ecc.


Che tipo di condizioni?
LP

1
@LP: probabilmente alcuni che l'OP non capisce -> " supera le mie attuali conoscenze " .
alk,

2
Dopo la modifica. definiscilo __STDC_WANT_IEC_60559_BFP_EXT__o passalo dalla riga di comando
LP

1
FWIW, POSIX richiede CHAR_BITdi essere 8, il che dovrebbe significare che CHAR_WIDTHdeve essere anche 8 su sistemi POSIX.
Andrew Henle,

4
@pliski hai fatto #defineprima del #include?
LegendofPedro

Risposte:


5

CHAR_WIDTHnon è standard, né lo sono altre *_WIDTHmacro, ma la larghezza di un tipo di carattere deve essere la stessa di CHAR_BIT*.

Per quanto riguarda le *_WIDTHmacro in generale, non sono strettamente necessarie in quanto sono calcolabili in base al tempo di compilazione dal valore massimo del corrispondente tipo senza segno, vale a dire, è possibile avere una #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)che si espande in un'espressione costante intera utilizzabile anche nei condizionali del preprocessore ( #if), sebbene le implementazioni siano un po 'oscure (vedi Esiste un modo per calcolare la larghezza di un tipo intero in fase di compilazione? ), ad esempio:

#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

Alcune persone lo fanno CHAR_BIT * sizeof(integer_type), ma questo non è strettamente portatile , perché presume integer_typeche non abbia bit di padding (di solito non lo è, ma teoricamente può averli), e non può nemmeno usarlo in #ifcondizioni.


* Sfortunatamente, per raccogliere queste informazioni, devi saltare tutto lo standard:

La larghezza di un tipo intero è (leggermente indirettamente) definita come il numero dei suoi bit non di riempimento ( 6.2.6.2p6 ).

6.2.6.2p2 dice signed charche non ha bit di riempimento. A causa del modo in cui gli interi possono essere rappresentati in C ( 6.2.6.2p2 ), ciò implica che unsigned charnon possono esserci nemmeno bit di padding e poiché chardevono avere gli stessi limiti di uno signed charo unsigned char( 5.2.4.2.1p2 ) pur avendo lo stesso sizeofvalore ( vale a dire 1, 6.5.3.4p4 ), una pianura charnon può avere alcun bit di riempimento e quindi CHAR_BIT == larghezza di ( char| signed char| unsigned char) .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.