为什么打印未初始化的bool数组作为整数会产生除0和1之外的值?

时间:2015-09-30 22:33:17

标签: c

(有关相关答案的类似问题,请参阅Mystery with bool data type。)

在调试程序时,我注意到在将未初始化的bool数组打印为整数时出现奇怪的输出。考虑一下这个C程序:

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

int main(void)
{
    int n = 30;
    bool* bools = malloc(n * sizeof(bool)); // Uninitialized memory.
    for (int i=0; i<n; ++i)
    {
        int x = bools[i];
        assert(x == 0 || x == 1);
        printf("%d ", x);
    }
    printf("\n");
    free(bools);
}

由于未初始化的bool数组,输出随每次运行而变化,当然基于先前的内存内容。我的理解是将一个bool转换为int应该总是产生0或1(参见上面的断言,它总是通过);但是,我经常看到这样的输出:

0 0 0 0 0 0 0 144 0 0 0 0 0 0 0 144 16 0 92 113 255 127 0 0 160 41 222 134 255 127

有人可以解释这个程序如何打印除0和1之外的任何东西吗?

更新:简短的回答是,将未初始化的 bool转换为int可以生成除0和1之外的值。(在我的情况下,bools存储为字节,所以它们的未初始化值可以是[0..255]中的任何值。)此外,上面的断言行似乎已经过优化,这使得这个问题更难以调试。

提供更多上下文:我最初编写的函数用于计算bool数组中的设置位数,例如:

int popcount(const bool* v, int n)
{
    int c=0;
    for (int i=0; i<n; ++i) c += v[i];
    return c;
}

我注意到有时会返回更大的结果,而这似乎是不可能的。问题是bool阵列未初始化。对阵列进行归零可以解决问题,但对于我来说如何将bool转换为int可以产生0或1之外的东西仍然没有意义。

2 个答案:

答案 0 :(得分:2)

因为限制布尔读取操作将实际值钳制为0或1是没有意义的。

未定义变量的值可以是适合变量大小的任何值。 bool通常占用一个字节(因为这是最小的可寻址单元),而在具有8位字节的系统上,它意味着bool可以存储256个不同的值。这就是为什么你看到的数字从0到255不等。

实现可以自由地假设你不会调用UB,这就是你看到0和1之外的值的原因。在没有UB的代码中,所有bool都将转换为0或1。

答案 1 :(得分:2)

bool_Bool)对象只能包含值01。在您的情况下,当您访问malloc返回的具有不确定值的未初始​​化内存时,您的程序会调用未定义的行为。

严格遵守的程序只会将_Bool个对象评估为01