‘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 等。
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)。