向量<bool>和printf </bool>的问题

时间:2011-08-25 15:54:59

标签: c++ vector

#include <vector>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, const char *argv[])
{
    vector<bool> a;
    a.push_back(false);
    int t=a[0];
    printf("%d %d\n",a[0],t);
    return 0;
}

此代码输出“5511088 1”。我以为它会是“0 0”。

任何人都知道为什么会这样?

4 个答案:

答案 0 :(得分:9)

%d格式说明符用于大小为整数的参数,因此printf函数期望两个参数都是int的大小。但是,您为它提供的参数不是int,而是由vector<bool>返回的可转换为bool的特殊对象。

这基本上导致printf函数将堆栈中的随机字节视为值的一部分,而事实上它们不是。

解决方案是将第一个参数转换为int

printf("%d %d\n", static_cast<int>(a[0]), t);

如果可能的话,更好的解决方案是优先选择printf以上的流,因为与printf不同,它们是类型安全的,这使得这种情况不可能发生:

cout << a[0] << " " << t << endl;

如果您正在寻找printf的类型安全替代方案 - 例如格式化,请考虑使用Boost Format库。

答案 1 :(得分:3)

%d格式说明符适用于int类型。所以,试试 -

cout << a[0] << "\t" << t << endl;

答案 2 :(得分:2)

答案的关键是向量不是真正的bool向量。它实际上是一个代理对象的向量,可以转换为int和&amp;布尔变量。这允许每个bool作为单个位存储,以获得更大的空间效率(以速度效率为代价),但是会引起许多问题,如此处所见。这个要求在一个轻松的时刻被投票进入了C ++标准,我相信大多数委员会成员现在都认为这是一个错误,但它在标准中并且我们很顽固地坚持它。

答案 3 :(得分:0)

问题由the specialization for bool of vectors触发。

<块引用>

标准库为 bool 定义了矢量模板的特殊化。这种特殊化的描述表明实现应该打包元素,以便每个 bool 只使用一位内存。 这被广泛认为是一个错误

基本上std::bool 使用 1 位而不是 1 个字节,因此您面临有关 printf 的未定义行为。

如果你真的愿意使用printf,你可以通过将std::bool定义为char并打印为整数%d来解决这个问题(隐式转换,1表示true 和 0 表示 false)。

#include <vector>
#include <iostream>
#include <stdio.h>

#define bool char // solved

using namespace std;

int main(int argc, const char *argv[])
{
    vector<bool> a;
    a.push_back(false);
    int t = a[0];
    printf("%d %d\n", a[0], t);
    return 0;
}