CHAR_WIDTH необъявленный

9

Я получаю сообщение об ошибке ‘CHAR_WIDTH’ undeclared при попытке скомпилировать эту простую программу:

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

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

с

gcc ./show_char_width.c -o show_char_width

и gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) версии 8.3.0 (x86_64-linux-gnu), скомпилированная GNU C версии 8.3.0, GMP версии 6.1.2, MPFR версии 4.0.2, MPC версии 1.1.0 , isl версия isl-0.20-GMP, ядро: 5.0.0-37-generic.

Как указано здесь, CHAR_WIDTH должен быть определен в limit.h, который включен в мою программу. Так почему я получаю эту ошибку?

С -vопцией я обнаружил, что библиотека будет искать в этих каталогах:

#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 содержит limit.h, который включает syslimits.h из того же каталога, который, в свою очередь, включает следующие limit.h, который, по моему пониманию, должен находиться в каталог / usr / include.

Макрос CHAR_WIDTH действительно определен в этих файлах, но при некоторых условиях, которые превышают мои реальные знания.

Условия, которые я нашел до сих пор:


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

а также :

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

Вот почему мне нужна твоя помощь.

Примечание: я получаю ту же ошибку со всеми другими макросами, описанными в A.5.1, в частности: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH и т. Д.

Плиски
источник
Какие условия?
LP
1
@LP: вероятно, некоторые, которых ОП не понимает -> « превосходят мои настоящие знания »
алк
2
После редактирования. определить __STDC_WANT_IEC_60559_BFP_EXT__или передать его с помощью командной строки
LP
1
FWIW, POSIX CHAR_BITдолжен быть равен 8, что должно означать CHAR_WIDTHтакже должно быть 8 в системах POSIX.
Эндрю Хенле
4
@pliski ты делал #defineдо #include?
LegendofPedro

Ответы:

5

CHAR_WIDTHне является стандартным, как и любые другие *_WIDTHмакросы, но ширина символьного типа должна быть такой же, как и в CHAR_BITлюбом случае *.

Что касается *_WIDTHмакросов в целом, они не являются строго необходимыми, так как они вычисляются во время компиляции из максимального значения соответствующего беззнакового типа, т. Е. Вы можете иметь #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)расширение, которое расширяется до целочисленного константного выражения, которое также можно использовать в условных выражениях препроцессора ( #if), хотя реализации немного неясны (см. Есть ли способ вычислить ширину целочисленного типа во время компиляции? ), например:

#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

Некоторые люди просто делают CHAR_BIT * sizeof(integer_type), но это не является строго переносимым , потому что предполагает, что у него integer_typeнет битов заполнения (обычно это не так, но теоретически они могут иметь их), и также не может использовать его в #ifусловных выражениях.


* К сожалению, чтобы получить эту информацию, вам нужно перейти по всему стандарту:

Ширина целочисленного типа (немного косвенно) определяется как число его битов, не дополняющих ( 6.2.6.2p6 ).

6.2.6.2p2 говорит, signed charчто не имеет никаких битов заполнения. Из-за того, что целые числа могут быть представлены в C ( 6.2.6.2p2 ), это подразумевает, что unsigned charбиты заполнения тоже не могут иметь, и поскольку charдолжны иметь те же ограничения, что и либо, signed charлибо unsigned char( 5.2.4.2.1p2 ), но иметь одинаковое sizeofзначение ( а именно 1, 6.5.3.4p4 ), у равнины также charне может быть битов заполнения, и поэтому CHAR_BIT == width of ( char| signed char| unsigned char) .

PSkocik
источник