我对CHAR_BIT感到困惑。我读过一些文章说宏CHAR_BIT是为了便于移植而存在的。要在代码中使用宏而不是像8这样的神奇数字,这是合理的。但是Lims.h来自glibc-headers,它的值固定为8。如果一个字节有超过8位(例如16位)的系统上安装了glibc-头,那么在编译时这是错误的吗?一个“字符”被分配给8位还是16位?
当我在Lims.h中将CHAR_BIT修改为9时,下面的代码仍然打印'8',怎么做?
#include <stdio.h>
#include <limits.h>
int
main(int argc, char **argv)
{
printf("%d\n", CHAR_BIT);
return 0;
}
以下是补充:我已阅读了所有答复,但仍不清楚。在实践中,使用#include <limits.h>
和CHAR_BIT,我可以遵守这一点。但那是另一回事。在这里,我想知道为什么会出现这种情况,首先它是glibc /usr/include/Lims.h中的一个固定值'8‘,当那些具有1字节!= 8位的系统安装了glibc时会发生什么情况?然后我发现'8’这个值甚至不是代码使用的实际值,所以'8‘没有任何意义?如果根本没有使用这个值,为什么要在那里加上'8‘呢?
谢谢,
发布于 2013-11-07 11:32:50
深入系统头文件可能是一种令人畏惧和不愉快的体验。glibc头文件很容易在头脑中造成许多混乱,因为在某些情况下,它们包含了其他系统头文件,这些文件覆盖了到目前为止定义的内容。
在limits.h
的情况下,如果仔细阅读头文件,您会发现只有在编译代码时才使用CHAR_BIT
的定义,而不是gcc,因为这一行:
#define CHAR_BIT 8
在以下几行的if
条件中:
/* If we are not using GNU CC we have to define all the symbols ourself.
Otherwise use gcc's definitions (see below). */
#if !defined __GNUC__ || __GNUC__ < 2
因此,如果您使用gcc编译代码(很可能是这样),则不会使用CHAR_BIT
的定义。这就是更改它的原因,您的代码仍然打印旧值。在头文件上向下滚动一点,您可以在使用GCC的情况下找到以下内容:
/* Get the compiler's limits.h, which defines almost all the ISO constants.
We put this #include_next outside the double inclusion check because
it should be possible to include this file more than once and still get
the definitions from gcc's header. */
#if defined __GNUC__ && !defined _GCC_LIMITS_H_
/* `_GCC_LIMITS_H_' is what GCC's file defines. */
# include_next <limits.h>
include_next
是GCC的扩展。你可以在这个问题上读到它的作用:下一个项目?
简单回答:它将使用您指定的名称(本例中为limits.h
)搜索下一个头文件,其中将包括GCC生成的limits.h
。在我的系统中,它恰好是/usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h
。
考虑以下方案:
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("%d\n", CHAR_BIT);
return 0;
}
使用此程序,您可以在gcc -E
的帮助下找到系统的路径,后者为包含的每个文件输出一条特殊行(参见http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html)。
因为#include <limits.h>
位于这个程序的第2行(我将其命名为test.c
),运行gcc -E test.c
可以让我找到包含的真正文件:
# 2 "test.c" 2
# 1 "/usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h" 1 3 4
您可以在该文件中找到这个:
/* Number of bits in a `char'. */
#undef CHAR_BIT
#define CHAR_BIT __CHAR_BIT__
注意undef
指令:它需要覆盖以前任何可能的定义。它的意思是:“不管CHAR_BIT
是什么,这才是真正的东西”。__CHAR_BIT__
是gcc的一个预定义常数。GCC的在线文档描述了它的如下方式:
__CHAR_BIT__
定义为字符数据类型的表示中使用的位数。它的存在是为了使给定数值限制的标准标头正确工作。不应直接使用此宏,而应包含适当的标头。
您可以通过一个简单的程序读取它的值:
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("%d\n", __CHAR_BIT__);
return 0;
}
然后运行gcc -E code.c
。请注意,您不应该像gcc的手册所提到的那样直接使用它。
显然,如果您在CHAR_BIT
中更改了/usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h
定义,或者您的系统中的任何等效路径,您将能够在代码中看到这种更改。考虑一下这个简单的程序:
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("%d\n", CHAR_BIT);
return 0;
}
将gcc的CHAR_BIT
limits.h
(即/usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h
中的文件)中的__CHAR_BIT__
定义从__CHAR_BIT__
更改为9将使此代码打印9。同样,在进行预处理之后,您可以停止编译过程;您可以使用gcc -E
进行测试。
,如果您正在用gcc以外的编译器编译代码呢?
那么,那么,默认的ANSI限制是假定的标准32位字。来自ANSI C标准第5.2.4.2.1段(积分类型<limits.h>
的大小):
下面给出的值应被适合于#if预处理指令中使用的常量表达式所取代。..。它们的实现定义值应等于或大于所显示的值(绝对值),并具有相同的符号。
POSIX要求兼容的平台具有CHAR_BIT == 8
。
当然,对于没有CHAR_BIT == 8
的机器,glibc的假设可能出错,但请注意,您必须处于不稳定的体系结构下,而不使用gcc,而且您的平台不兼容POSIX。不太可能。
但是,请记住,“实现定义”意味着编译器编写人员选择发生了什么。因此,即使您没有使用gcc
进行编译,您的编译器也有可能定义某种类型的__CHAR_BIT__
等效。即使glibc不使用它,您也可以做一些研究,直接使用编译器的定义。这通常是不好的做法--您将编写面向特定编译器的代码。
请记住,您永远不应该干扰系统头文件。当您使用错误而重要的常量(如CHAR_BIT
)编译东西时,可能会发生非常奇怪的事情。此操作仅用于教育目的,并始终将原始文件还原回。
发布于 2013-10-31 14:57:22
对于给定的系统,永远不应该更改CHAR_BIT
。CHAR_BIT
的值以最小可寻址存储单元(“字节”)的位为单位指定大小,因此即使使用16位字符(UCS-2或UTF-16)的系统也很可能具有CHAR_BIT == 8
。
几乎所有现代系统都有CHAR_BIT == 8
;某些DSP的C实现可能会将其设置为16或32。
CHAR_BIT
的值并不控制字节中的位数,它将其记录下来,并允许用户代码引用它。例如,对象中的位数是sizeof object * CHAR_BIT
。
如果编辑系统的<limits.h>
文件,这不会改变系统的实际特征;它只会给出一个不一致的系统。这就像对编译器进行黑客攻击,因此它定义了符号_win32
而不是_linux
;这不会神奇地将您的系统从Windows更改为Linux,它只会破坏系统。
CHAR_BIT
是每个系统的只读常量.它是由系统开发人员定义的。你不能改变它,甚至不要尝试。
据我所知,glibc只在8位字节的系统上工作。理论上可以修改它,因此它可以在其他系统上工作,但是如果没有大量的开发工作,您甚至可能无法在一个16位字节的系统上安装它。
至于为什么黑客攻击limits.h
文件并没有改变您为CHAR_BIT
获得的值,系统标头是复杂的,不打算进行适当的编辑。当我在系统上编译一个只有#include <limits.h>
的小文件时,它直接或间接地包括:
/usr/include/features.h
/usr/include/limits.h
/usr/include/linux/limits.h
/usr/include/x86_64-linux-gnu/bits/local_lim.h
/usr/include/x86_64-linux-gnu/bits/posix1_lim.h
/usr/include/x86_64-linux-gnu/bits/posix2_lim.h
/usr/include/x86_64-linux-gnu/bits/predefs.h
/usr/include/x86_64-linux-gnu/bits/wordsize.h
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
/usr/include/x86_64-linux-gnu/gnu/stubs.h
/usr/include/x86_64-linux-gnu/sys/cdefs.h
/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h
/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h
其中两个文件具有用于#define
的CHAR_BIT
指令,一个将其设置为8
,另一个设置为__CHAR_BIT__
。我不知道(也不需要关心)这些定义中的哪一个真正生效。我需要知道的是,#include <limits.h>
会给出CHAR_BIT
的正确定义--只要我不做任何破坏系统的事情。
发布于 2013-10-31 14:23:19
关键是,在为不同大小的系统进行编译时,CHAR_BIT会更改为正确的大小。
https://stackoverflow.com/questions/19708810
复制相似问题