CHAR_WIDTH nicht deklariert

9

Ich erhalte die Fehlermeldung, ‘CHAR_WIDTH’ undeclared wenn ich versuche, dieses einfache Programm zu kompilieren:

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

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

mit

gcc ./show_char_width.c -o show_char_width

und gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) Version 8.3.0 (x86_64-linux-gnu), kompiliert von GNU C Version 8.3.0, GMP Version 6.1.2, MPFR Version 4.0.2, MPC Version 1.1.0 , isl version isl-0.20-GMP, kernel: 5.0.0-37-generic.

Wie hier angegeben, sollte CHAR_WIDTH in limits.h definiert werden, das in meinem Programm enthalten ist. Warum bekomme ich diesen Fehler?

Mit der -vOption habe ich festgestellt, dass die Bibliothek in diesen Verzeichnissen durchsucht wird:

#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 enthält ein Limits.h, das syslimits.h aus demselben Verzeichnis enthält, das wiederum die nächsten Limits enthält.h, die sich nach meinem Verständnis in befinden sollten das Verzeichnis / usr / include.

Das CHAR_WIDTH-Makro ist zwar in diesen Dateien definiert, jedoch unter bestimmten Bedingungen, die mein tatsächliches Wissen überschreiten.

Die Bedingungen, die ich bis jetzt gefunden habe, sind:


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

und :

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

Deshalb brauche ich deine Hilfe.

Hinweis: Ich erhalte den gleichen Fehler mit allen anderen in A.5.1 beschriebenen Makros, insbesondere: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH usw.

pliski
quelle
Welche Bedingungen?
LPs
1
@LP: wahrscheinlich einige, die das OP nicht versteht -> " meine tatsächlichen Kenntnisse übertreffen. "
alk
2
Nach der Bearbeitung. Definieren __STDC_WANT_IEC_60559_BFP_EXT__oder übergeben Sie es über die Befehlszeile
LPs
1
FWIW, POSIX muss CHAR_BIT8 sein, was bedeuten sollte, CHAR_WIDTHdass es auf POSIX-Systemen auch 8 sein muss.
Andrew Henle
4
@pliski hast du #definevor dem #include?
LegendofPedro

Antworten:

5

CHAR_WIDTHist weder Standard noch andere *_WIDTHMakros, aber die Breite eines Zeichentyps muss mit CHAR_BIT* identisch sein.

Wie für *_WIDTHMakros in der Regel sind sie nicht unbedingt erforderlich , da sie Compile-Zeit-berechenbar aus dem Maximalwert des entsprechenden unsigned - Typ sind, das heißt, können Sie eine haben , #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)dass sich ausdehnt auf einen ganzzahligen konstanten Ausdruck, der in Präprozessor conditionals auch verwendbar ist ( #if), obwohl Implementierungen etwas unklar sind (siehe Gibt es eine Möglichkeit, die Breite eines Integer-Typs zur Kompilierungszeit zu berechnen? ), z.

#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

Einige Leute tun dies einfach CHAR_BIT * sizeof(integer_type), aber das ist nicht unbedingt portabel , da davon ausgegangen wird , dass es integer_typekeine Füllbits gibt (normalerweise nicht, aber theoretisch kann es sie haben) und es auch nicht unter #ifBedingungen verwenden kann.


* Um diese Informationen zu erhalten, müssen Sie leider über den Standard springen:

Die Breite eines Integer-Typs ist (leicht indirekt) definiert als die Anzahl seiner nicht auffüllenden Bits ( 6.2.6.2p6 ).

6.2.6.2p2 sagt, signed chardass keine Füllbits vorhanden sind. Aufgrund der Art und Weise, wie Ganzzahlen in C ( 6.2.6.2p2 ) dargestellt werden können, bedeutet unsigned chardies , dass auch keine Auffüllbits vorhanden sein dürfen und dass chardiese dieselben Grenzen wie entweder signed charoder unsigned char( 5.2.4.2.1p2 ) haben müssen, während sie denselben sizeofWert haben ( nämlich 1, 6.5.3.4p4 ), eine Ebene charkann auch keine Füllbits haben, und so CHAR_BIT == Breite von ( char| signed char| unsigned char) .

PSkocik
quelle