CHAR_WIDTH 未声明

pli*_*ski 10 c gcc

‘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);
}
Run Code Online (Sandbox Code Playgroud)

gcc ./show_char_width.c -o show_char_width
Run Code Online (Sandbox Code Playgroud)

和 gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) version 8.3.0 (x86_64-linux-gnu) 由 GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0 编译, isl 版本 isl-0.20-GMP,内核:5.0.0-37-generic。

如此处所述 CHAR_WIDTH 应在我的程序中包含的limits.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
Run Code Online (Sandbox Code Playgroud)

/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed 包含一个limits.h,其中包含来自同一个目录的syslimits.h,而后者又包含下一个limits.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
Run Code Online (Sandbox Code Playgroud)

和 :

#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
/* TS 18661-1 widths of integer types.  */
# undef CHAR_WIDTH
# define CHAR_WIDTH __SCHAR_WIDTH__
Run Code Online (Sandbox Code Playgroud)

这就是为什么我需要你的帮助。

注意:我遇到了与 A.5.1 中描述的所有其他宏相同的错误,特别是:SCHAR_WIDTH、INT_WIDTH、LONG_WIDTH 等。

PSk*_*cik 5

CHAR_WIDTH不是标准的,也不是任何其他*_WIDTH宏,但字符类型的宽度必须与CHAR_BIT任何情况相同*。

至于*_WIDTH一般的宏,它们不是严格需要的,因为它们可以从相应无符号类型的最大值进行编译时计算,即,您可以将 a#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
Run Code Online (Sandbox Code Playgroud)

有些人只是这样做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 charor unsigned char( 5.2.4.2.1p2 )相同的限制,同时具有相同的sizeof值 (即 1, 6.5.3.4p4 ),一个普通的char也不能有任何填充位,所以CHAR_BIT == 宽度 ( char| signed char| unsigned char)