C 为什么将未初始化的布尔数组打印为整数会产生0和1以外的值?

C 为什么将未初始化的布尔数组打印为整数会产生0和1以外的值?,c,C,(另请参见相关答案的类似问题。) 在调试程序时,我注意到将未初始化的布尔数组打印为整数时出现了奇怪的输出。考虑这个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)); // Un

(另请参见相关答案的类似问题。)


在调试程序时,我注意到将未初始化的布尔数组打印为整数时出现了奇怪的输出。考虑这个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);
}
有人能解释一下这个程序如何打印除0和1之外的任何东西吗

更新:简单的回答是,将未初始化的布尔值强制转换为int可以生成0和1以外的值。(在我的例子中,bool被存储为字节,因此它们的未初始化值可以是[0..255]中的任何值。)此外,上面的断言行似乎被优化了,这使得这个问题更难调试


为了提供更多的上下文:我最初编写了一个函数来计算布尔数组中的设置位数,例如:

int popcount(const bool* v, int n)
{
    int c=0;
    for (int i=0; i<n; ++i) c += v[i];
    return c;
}
intpopcount(常量布尔*v,intn)
{
int c=0;

对于(int i=0;i,因为将布尔读取操作限制为将实际值钳制为0或1是没有意义的

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

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

A
bool
\u bool
)对象只能保存值
0
1
。在您的情况下,当您访问由具有不确定值的
malloc
返回的未初始化内存时,程序调用未定义的行为


严格一致的程序只会对
\u Bool
对象进行
0
1

求值,因为访问未初始化的数据会导致未定义的行为,所以任何结果都是可能的。这解释了为什么它会打印大于1的值,但为什么
assert
不会触发?@Barmar编译器会对其进行优化作为一个有效的<代码> BOOL 不应该包含比<代码> 0 或<代码> 1 > /代码>的其他内容。优化可以考虑不发生未定义的行为。
int popcount(const bool* v, int n)
{
    int c=0;
    for (int i=0; i<n; ++i) c += v[i];
    return c;
}