【问题标题】:CHAR_WIDTH undeclaredCHAR_WIDTH 未声明
【发布时间】:2026-01-04 00:55:02
【问题描述】:

我得到了错误 ‘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。

here 所述,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

/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

和:

#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 等。

【问题讨论】:

  • ``` /* 在 GCC 7 之前,GCC 的 没有定义整数宽度宏,或者如果使用 _GNU_SOURCE 而不是 STDC_WANT_IEC_60559_BFP_EXT 来启用此功能. */ #if __GLIBC_USE (IEC_60559_BFP_EXT) # ifndef CHAR_WIDTH # 定义 CHAR_WIDTH 8 # endif```
  • @LP:可能有些OP不理解-->“超出我的实际知识。
  • 我用 /usr/include/limits.h 中的一些代码编辑了帖子
  • 编辑后。定义__STDC_WANT_IEC_60559_BFP_EXT__ 或通过命令行传递它
  • @pliski 你在#define 之前是#include 吗?

标签: c gcc


【解决方案1】:

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

至于一般的*_WIDTH 宏,它们并不是严格需要的,因为它们可以从相应的无符号类型的最大值进行编译时计算,即,您可以拥有一个扩展为整数的#define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax)也可用于预处理器条件 (#if) 的常量表达式,尽管实现有点模糊(请参阅 Is there any way to compute the width of an integer type at compile-time?),例如:

#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 charunsigned char (@ 987654325@) 虽然具有相同的 sizeof 值(即 1,6.5.3.4p4),但普通的 char 也不能有任何填充位,因此 CHAR_BIT == 宽度为 (char |signed char|unsigned char).

【讨论】: