Неозначено: 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-fix містять обмеження.h, які включають syslimits.h з того самого dir, що, в свою чергу, включає наступні 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 тощо.


Які умови?
LPs

1
@LP: напевно, деякі, яких ОП не розуміє -> " перевищують мої фактичні знання "
алк

2
Після редагування. визначте __STDC_WANT_IEC_60559_BFP_EXT__або передайте його командним рядком
LPs

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 == ширина ( char| signed char| unsigned char) .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.