修复了各种系统上的 CHAR_BIT? [英] fixed CHAR_BIT on various systems?

查看:28
本文介绍了修复了各种系统上的 CHAR_BIT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对limits.h 中的CHAR_BIT 感到困惑.我读过一些文章说宏 CHAR_BIT 是为了可移植性.在代码中使用宏而不是像 8 这样的幻数,这是合理的.但是limits.h来自glibc-headers,它的值固定为8.如果glibc-headers安装在一个字节超过8位(比如16位)的系统上,编译时会出错吗?'char' 分配 8 位或 16 位?

I am confused about CHAR_BIT in limits.h. I have read some articles saying the macro CHAR_BIT is there for portability. To use the macro not a magic number like 8 in code, this is reasonable. But limits.h is from glibc-headers and it's value is fixed as 8. If glibc-headers is installed on a system on which a byte has more than 8 bits (say 16 bits), is that wrong when compiling? A 'char' is assigned 8 bits or 16 bits?

而当我在limits.h中将CHAR_BIT修改为9,下面的代码还是打印'8',怎么办?

And when I modified CHAR_BIT to 9 in limits.h, the following code still prints '8', how?

#include <stdio.h>
#include <limits.h>

int
main(int argc, char **argv)
{
    printf("%d
", CHAR_BIT);
    return 0;
}

以下是补充:我已经阅读了所有回复,但仍然不清楚.在实践中,#include <limits.h> 并使用 CHAR_BIT,我可以遵守.但那是另一回事.这里我想知道为什么会这样,首先它是glibc/usr/include/limits.h中的固定值'8',当那些有1字节!= 8位的系统安装了glibc时会发生什么;然后我发现值'8'甚至不是代码使用的真实值,所以'8'意味着什么?如果根本不使用该值,为什么要放'8'呢?

The following is supplementary: I've read all replies so for, but still not clear. In practice, #include <limits.h> and use CHAR_BIT, I can obey that. But that's another thing. Here I want to know why it appears that way, first it is a fixed value '8' in glibc /usr/include/limits.h, what happens when those systems which has 1 byte != 8 bits are installed with glibc; then I found the value '8' is not even the real value the code is using, so '8' means nothing there? Why put '8' there if the value is not used at all?

谢谢,

推荐答案

深入研究系统头文件可能是令人生畏和不愉快的经历.glibc 头文件很容易在您的脑海中造成很多混乱,因为它们在某些情况下包含其他系统头文件,这些头文件会覆盖迄今为止定义的内容.

Diving into system header files can be a daunting and unpleasant experience. glibc header files can easily create a lot of confusion in your head, because they include other system header files under certain circumstances that override what has been defined so far.

limits.h为例,如果你仔细阅读头文件,你会发现CHAR_BIT的定义只在你编译没有gcc的代码时使用,因为这一行:

In the case of limits.h, if you read the header file carefully, you will find that the definition for CHAR_BIT is only used when you compile code without gcc, since this line:

#define CHAR_BIT 8

在上面几行的 if 条件内:

Is inside an if condition a few lines above:

/* 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 的情况下找到它:

Thus, if you compile your code with gcc, which is most likely the case, this definition for CHAR_BIT will not be used. That's why you change it and your code still prints the old value. Scrolling down a little bit on the header file, you can find this for the case that you're using 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 扩展.您可以在这个问题中了解它的作用:Why would one在项目中使用#include_next?

include_next is a GCC extension. You can read about what it does in this question: Why would one use #include_next in a project?

简短的回答:它将搜索具有您指定名称的下一个头文件(在本例中为 limits.h),并将包含 GCC 生成的 limits.h.在我的系统中,它恰好是 /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h.

Short answer: it will search for the next header file with the name you specify (limits.h in this case), and it will include GCC's generated limits.h. In my system, it happens to be /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h.

考虑以下程序:

#include <stdio.h>
#include <limits.h>

int main(void) {
  printf("%d
", CHAR_BIT);
  return 0;
}

使用这个程序,您可以在 gcc -E 的帮助下找到系统的路径,它会为包含的每个文件输出一个特殊的行(参见 http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html)

With this program, you can find the path for your system with the help of gcc -E, which outputs a special line for each file included (see http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html)

因为 #include <limits.h> 在这个程序的第 2 行,我将它命名为 test.c,运行 gcc -E test.c 允许我找到包含的真实文件:

Because #include <limits.h> is on line 2 of this program, which I named test.c, running gcc -E test.c allows me to find the real file that is being included:

# 2 "test.c" 2
# 1 "/usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h" 1 3 4

你可以在那个文件中找到这个:

You can find this in that file:

/* Number of bits in a `char'.  */
#undef CHAR_BIT
#define CHAR_BIT __CHAR_BIT__

注意 undef 指令:它需要覆盖任何可能的先前定义.它是在说:忘记任何 CHAR_BIT 是什么,这是真实的东西".__CHAR_BIT__ 是一个 gcc 预定义常量.GCC 的在线文档是这样描述的:

Note the undef directive: it is needed to override any possible previous definitions. It is saying: "Forget whatever CHAR_BIT was, this is the real thing". __CHAR_BIT__ is a gcc predefined constant. GCC's online documentation describes it in the following way:

__CHAR_BIT__定义为用于表示 char 数据类型的位数.它的存在是为了使标准标题给定数字限制正常工作.你不应该直接使用这个宏;而是包含适当的标题.

__CHAR_BIT__ Defined to the number of bits used in the representation of the char data type. It exists to make the standard header given numerical limits work correctly. You should not use this macro directly; instead, include the appropriate headers.

你可以用一个简单的程序来读取它的值:

You can read its value with a simple program:

#include <stdio.h>
#include <limits.h>

int main(void) {
  printf("%d
", __CHAR_BIT__);
  return 0;
}

然后运行gcc -E code.c.请注意,您不应该直接使用它,正如 gcc 的手册页所述.

And then running gcc -E code.c. Note that you shouldn't use this directly, as gcc's manpage mentions.

显然,如果您更改 /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h 内的 CHAR_BIT 定义,或其他等效路径在您的系统中,您将能够在代码中看到此更改.考虑这个简单的程序:

Obviously, if you change CHAR_BIT definition inside /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h, or whatever the equivalent path is in your system, you will be able to see this change in your code. Consider this simple program:

#include <stdio.h>
#include <limits.h>

int main(void) {
  printf("%d
", CHAR_BIT);
  return 0;
}

改变gcc的limits.h中的CHAR_BIT定义(即/usr/lib/gcc/i486-linux-gnu/4.7/中的文件include-fixed/limits.h) 从 __CHAR_BIT__ 到 9 将使此代码打印 9.同样,您可以在预处理发生后停止编译过程;您可以使用 gcc -E 对其进行测试.

Changing CHAR_BIT definition in gcc's limits.h (that is, the file in /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h) from __CHAR_BIT__ to 9 will make this code print 9. Again, you can stop the compilation process after preprocessing takes place; you can test it with gcc -E.

如果您使用 gcc 以外的编译器编译代码怎么办?

好吧,就这样吧,默认 ANSI 限制假定用于标准 32 位字.来自 ANSI C 标准中的第 5.2.4.2.1 段(整数类型的大小 ):

Well, then be it, default ANSI limits are assumed for standard 32-bit words. From paragraph 5.2.4.2.1 in ANSI C standard (sizes of integral types <limits.h>):

下面给出的值应替换为常量表达式适用于#if 预处理指令.[...] 他们的实现定义的值应在大小上相等或更大(绝对值)与所示的相同,符号相同.

The values given below shall be replaced by constant expressions suitable for use in #if preprocessing directives. [...] Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.

  • 不是位域(字节)的最小对象的位数

  • number of bits for smallest object that is not a bit-field (byte)

CHAR_BIT 8

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

POSIX mandates that a compliant platform have CHAR_BIT == 8.

当然,对于没有 CHAR_BIT == 8 的机器,glibc 的假设可能会出错,但请注意,您必须处于不寻常的架构下并且不使用 gcc 并且您的平台不符合 POSIX.不太可能.

Of course, glibc's assumptions can go wrong for machines which do not have CHAR_BIT == 8, but note that you must be under an unsual architecture AND not use gcc AND your platform is not POSIX compliant. Not very likely.

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

Remember, however, that "implementation defined" means that the compiler writer chooses what happens. Thus, even if you're not compiling with gcc, there is a chance that your compiler has some sort of __CHAR_BIT__ equivalent defined. Even though glibc will not use it, you can do a little research and use your compiler's definition directly. This is generally bad practice - you will be writing code that is geared towards a specific compiler.

请记住,您永远不应该弄乱系统头文件.当您使用错误且重要的常量(如 CHAR_BIT)编译内容时,可能会发生非常奇怪的事情.仅出于教育目的执行此操作,并始终恢复原始文件.

Keep in mind that you should never be messing with system header files. Very weird things can happen when you compile stuff with wrong and important constants like CHAR_BIT. Do this for educational purposes only, and always restore the original file back.

这篇关于修复了各种系统上的 CHAR_BIT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆