【问题标题】:If bool is a macro for int, why is it a different size?如果 bool 是 int 的宏,为什么它的大小不同?
【发布时间】:2012-05-17 05:01:50
【问题描述】:

我希望有人能解释原因

#include <stdbool.h>

printf("size of bool %d\n", sizeof(bool));
printf("size of int %d\n", sizeof(int));

输出到

size of bool 1
size of int 4

我查看了http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdbool.h.html,这似乎表明 bool 本质上是 _Bool 的宏,当设置为 true 或 false 时,它​​实际上只是整数常量的宏。如果是整数,为什么大小不一样?

我之所以这么问,是因为调试一个我们没有为其分配足够内存的程序花费的时间太长了。

【问题讨论】:

  • 只是好奇——如果bool 比你预期的,你怎么没有分配足够的内存?
  • @detly 好吧,老实说我们不确定。我们有一个 bool 数组,它总是导致分段错误,直到我们将 malloc(x*sizeof(bool)) 乘以 malloc(4*x*sizeof(bool)) 这可能是完全不同的东西,但这解决了问题并让我想到了这个问题。
  • 您在声明三重指针 - 您在什么级别分配 x*sizeof(bool)?对于前两个级别,即指向指针的指针,您必须分配sizeof(bool*),因为sizeof(bool*) 可能不等于sizeof(bool)
  • @birrtree 这很有趣。我们为每个级别分配了x*sizeof(bool)。但是既然你提到了它,(我坐下来想一想)我们需要为指针分配内存,而不是为除最后一个级别之外的所有级别分配实际的bool。哇!正如我在您的回答中提到的,这非常有教育意义且很有帮助!
  • 是的,对于前两个级别,由于它们是指向指针的指针,因此您必须分配空间来存储指针,因此请使用 x*sizeof(bool*) 之类的东西而不是 x*sizeof(bool)。这样您就不必执行4*x*sizeof(bool) 之类的操作,因为这只会在指针为 4 字节宽(32 位程序)的系统上为您提供帮助。在 64 位程序中,您会再次遇到内存崩溃。 sizeof(bool*) 将在 32 位或 64 位上正常工作。

标签: c memory int boolean


【解决方案1】:

C99 中的 _Bool 类型(stdbool.h 中的bool)没有标准定义的大小,但根据 C99 标准的第 6.2.5 节:

2 An object declared as type _Bool is large enough to store the values 0 and 1.

在 C 中,最小的可寻址对象(除了位域)是char,它至少有 8 位宽,sizeof(char) 始终是1

_Boolbool 因此具有至少为1sizeof,并且在我见过的大多数实现中,sizeof(bool) / sizeof(_Bool)1

如果您查看 GCC 的 stdbool.h,您会得到:

 #define bool    _Bool
 #if __STDC_VERSION__ < 199901L && __GNUC__ < 3
 typedef int _Bool;
 #endif

 #define false   0
 #define true    1

所以如果在编译时使用旧版本的 GCC 和旧版本的 C 标准,您将使用 int 作为 _Bool 类型。

当然,作为一件有趣的事情,看看这个:

#include <stdio.h>
#include <stdbool.h>

int main() {
   printf("%zu\n", sizeof(_Bool));
   printf("%zu\n", sizeof(true));
   printf("%zu\n", sizeof(false));

}

输出:

λ > ./a.out 
1
4
4

GCC 4.2.4、Clang 3.0 和 GCC 4.7.0 的输出都相同。正如 trinithis 指出的那样,sizeof(true)sizeof(false) 产生更大的大小,因为它们采用 int 文字的大小,至少为 sizeof(int)

【讨论】:

  • 感谢您的回答。我仍然从 C 开始,我从您的回复中学到的不仅仅是问题的答案。
  • sizeof 是有意义的,因为它们是 int 字面量的#defines。一个 int 字面量的 sizeof 是 sizeof int。在这种情况下,true 和 false 是 int 字面量。
  • @trinithis - 是的,只是想提请注意,如果您针对类型与标头提供的其他宏进行尝试,您会得到不同的sizeofs。
  • 就像挑剔一样,size_t 的正确printf 格式是z,这里%zu 可以解决问题。
  • 感谢@JensGustedt - 已编辑以反映正确的修饰符。
【解决方案2】:

C99 标准引入了_Bool 类型。 _Bool 保证足够大以容纳整数常量 0 或 1 ,这并不一定意味着它是一个 int。实际大小取决于编译器。

【讨论】:

    【解决方案3】:

    我很确定它取决于您的编译器,也许您的编译器使用的是 byte 而不是 int 作为 bool?无论哪种方式,如果您使用 sizeof() 来知道要分配多少内存,您都不应该有内存分配问题,例如,如果您想分配 10 个布尔值的内存,不要分配 10 * 4,而是执行 10 * sizeof (bool) 所以你不会出错。

    【讨论】:

      【解决方案4】:

      它是一个整数,但不是intcharshortintlonglong long等都是整数。 char 保证大小为 1。其余的至少与 char 一样大(如果int 不大于 char,很难想象如何使 I/O 系统正常工作) .还有一个从charlong long 的必需顺序(我在上面列出的顺序相同),其中每种类型的范围必须至少与其前辈一样多。

      但是,除此之外,您无法保证整数类型的大小。具体来说,char 是唯一一种具有保证大小的“基本”类型(尽管有像 int8_tint32_t 这样的类型具有保证大小)。

      【讨论】:

        【解决方案5】:

        正如我从将代码从 Windows 移植到 Unix 中所知道的,您永远无法确定数据类型的大小。这取决于操作系统,有时甚至取决于您使用的编译器。

        stdbool.h 的规范只说 TRUE 和 FALSE 映射到一个整数(1 和 0)。这并不意味着数据类型 bool 是 int 类型。根据我的经验,bool 是可用的最小数据类型(即 char 或 byte):

        bool flag = TRUE; -> byte flag = 0x01;
        

        在 eclipse CDT 和 Visual Studio 中,您可以按照宏定义来查看数据类型背后的真正含义。

        所以我建议你总是向你的编译器询问分配足够内存所需的内存空间(这也是我在很多库中看到的):

        malloc(4*sizeof(bool));
        

        我希望这会有所帮助。

        【讨论】:

        • 有趣。我不知道你可以在 eclipse 中遵循宏定义。学到更多的东西总是很高兴,而不仅仅是原始问题的答案!
        【解决方案6】:

        _Bool 是编译器原生的,在 C99 中定义,可以像 gcc -std=c99 一样激活; stdbool.h #define bool 为 _Bool,true 和 false 为简单的 int 字面量,非常适合该 _Bool。

        【讨论】:

          猜你喜欢
          • 2018-08-22
          • 2019-02-08
          • 1970-01-01
          • 2017-06-01
          • 2021-08-24
          • 2010-09-20
          • 2021-06-25
          • 2013-03-26
          相关资源
          最近更新 更多