固定CHAR_BIT在各种系统上? [英] fixed CHAR_BIT on various systems?

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

问题描述

我对limits_B中的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\n", 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 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扩展。您可以阅读此问题中的内容:为什么会在项目中使用#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\n", 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 code> 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\n", __CHAR_BIT__);
  return 0;
}

然后运行 gcc -E code.c 。注意,你不应该直接使用它,如gcc的manpage所述。

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

显然,如果你改变 CHAR_BIT /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/limits.h 内部,或者无论系统中的等效路径是什么,能够在您的代码中看到此更改。考虑这个简单的程序:

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\n", CHAR_BIT);
  return 0;
}

更改 CHAR_BIT 定义在gcc的 limits.h (即 /usr/lib/gcc/i486-linux-gnu/4.7/include-fixed/ limit .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?

那么,对于标准的32位字,默认使用ANSI限制。从ANSI C标准(整数类型< limits.h> )的第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

CHAR_BIT 8

POSIX要求合规平台具有 CHAR_BIT == 8

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

当然,glibc的假设对于没有 CHAR_BIT == 8 ,但请注意,您必须是一个非现实的架构,而不是使用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天全站免登陆