首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >修正了不同系统上的CHAR_BIT?

修正了不同系统上的CHAR_BIT?
EN

Stack Overflow用户
提问于 2013-10-31 14:11:32
回答 3查看 6.5K关注 0票数 3

我对CHAR_BIT感到困惑。我读过一些文章说宏CHAR_BIT是为了便于移植而存在的。要在代码中使用宏而不是像8这样的神奇数字,这是合理的。但是Lims.h来自glibc-headers,它的值固定为8。如果一个字节有超过8位(例如16位)的系统上安装了glibc-头,那么在编译时这是错误的吗?一个“字符”被分配给8位还是16位?

当我在Lims.h中将CHAR_BIT修改为9时,下面的代码仍然打印'8',怎么做?

代码语言:javascript
运行
复制
#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‘呢?

谢谢,

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-11-07 11:32:50

深入系统头文件可能是一种令人畏惧和不愉快的体验。glibc头文件很容易在头脑中造成许多混乱,因为在某些情况下,它们包含了其他系统头文件,这些文件覆盖了到目前为止定义的内容。

limits.h的情况下,如果仔细阅读头文件,您会发现只有在编译代码时才使用CHAR_BIT的定义,而不是gcc,因为这一行:

代码语言:javascript
运行
复制
#define CHAR_BIT 8

在以下几行的if条件中:

代码语言:javascript
运行
复制
/* 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的情况下找到以下内容:

代码语言:javascript
运行
复制
 /* 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

考虑以下方案:

代码语言:javascript
运行
复制
#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可以让我找到包含的真正文件:

代码语言:javascript
运行
复制
# 2 "test.c" 2
# 1 "/usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h" 1 3 4

您可以在该文件中找到这个:

代码语言:javascript
运行
复制
/* Number of bits in a `char'.  */
#undef CHAR_BIT
#define CHAR_BIT __CHAR_BIT__

注意undef指令:它需要覆盖以前任何可能的定义。它的意思是:“不管CHAR_BIT是什么,这才是真正的东西”。__CHAR_BIT__是gcc的一个预定义常数。GCC的在线文档描述了它的如下方式:

__CHAR_BIT__定义为字符数据类型的表示中使用的位数。它的存在是为了使给定数值限制的标准标头正确工作。不应直接使用此宏,而应包含适当的标头。

您可以通过一个简单的程序读取它的值:

代码语言:javascript
运行
复制
#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定义,或者您的系统中的任何等效路径,您将能够在代码中看到这种更改。考虑一下这个简单的程序:

代码语言:javascript
运行
复制
#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预处理指令中使用的常量表达式所取代。..。它们的实现定义值应等于或大于所显示的值(绝对值),并具有相同的符号。

  • 非位字段的最小对象的位数(字节) CHAR_BIT 8

POSIX要求兼容的平台具有CHAR_BIT == 8

当然,对于没有CHAR_BIT == 8的机器,glibc的假设可能出错,但请注意,您必须处于不稳定的体系结构下,而不使用gcc,而且您的平台不兼容POSIX。不太可能。

但是,请记住,“实现定义”意味着编译器编写人员选择发生了什么。因此,即使您没有使用gcc进行编译,您的编译器也有可能定义某种类型的__CHAR_BIT__等效。即使glibc不使用它,您也可以做一些研究,直接使用编译器的定义。这通常是不好的做法--您将编写面向特定编译器的代码。

请记住,您永远不应该干扰系统头文件。当您使用错误而重要的常量(如CHAR_BIT )编译东西时,可能会发生非常奇怪的事情。此操作仅用于教育目的,并始终将原始文件还原回。

票数 14
EN

Stack Overflow用户

发布于 2013-10-31 14:57:22

对于给定的系统,永远不应该更改CHAR_BITCHAR_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>的小文件时,它直接或间接地包括:

代码语言:javascript
运行
复制
/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

其中两个文件具有用于#defineCHAR_BIT指令,一个将其设置为8,另一个设置为__CHAR_BIT__。我不知道(也不需要关心)这些定义中的哪一个真正生效。我需要知道的是,#include <limits.h>会给出CHAR_BIT的正确定义--只要我不做任何破坏系统的事情。

票数 6
EN

Stack Overflow用户

发布于 2013-10-31 14:23:19

关键是,在为不同大小的系统进行编译时,CHAR_BIT会更改为正确的大小。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19708810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档