我得到了错误‘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 C版本8.3.0,GMP版本6.1.2,MPFR版本4.0.2,MPC版本1.1.0编译的GNU C17(Ubuntu 8.3.0-6ubuntu1)版本8.3.0(x86_64-linux-gnu) ,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等。
最佳答案
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 char
或unsigned char
(5.2.4.2.1p2)相同的限制,同时具有相同的sizeof
值(即1) (6.5.3.4p4),普通的char
也不能有任何填充位,因此CHAR_BIT
==(char
| signed char
| unsigned char
)的宽度。关于CHAR_WIDTH未声明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59212052/