为什么MSVC会给我'错误'的结果?

时间:2013-06-17 18:12:34

标签: c++ visual-c++

我期待addr addr 33 44其中addr可以是任何东西,两者都是相同的。

在gcc I get that中。但是在MSVC中,我得到了

8D3678 0 9257096 9257096
8D3678 0 9257104 9257104
8D3678 0 9257112 9257112

WTF!?!我没有警告/错误。有没有人愿意解释为什么最后两个值不是33 44以及为什么它们是相同的(并且非常错误)。

#include <cstdio>
#include <vector>
class Person{
public:
    int age;
    int weight;
    Person(int age, int weight):age(age), weight(weight){}
};
int main() {
    std::vector<Person> ls;
    Person p(33, 44);
    ls.push_back(p);
    ls.push_back(p);
    ls.push_back(p);
    for(auto i=ls.begin();i!=ls.end();++i){
        printf("%X %X %d %d\n", i, &(*i), (*i).age, (*i).weight);
    }

}

3 个答案:

答案 0 :(得分:8)

您正在传递vector::iterator作为printf参数,其中需要一个整数。这给出了未定义的行为。 (顺便说一下,将指针作为第二个参数传递也是如此;但这可能会给出您在32位平台上所期望的结果)。 printf未经过类型检查,这就是您通常应该使用C ++风格的I / O的原因。

GCC的实现只是指针的包装,所以你不小心得到了你期望的结果; MSVC的实现似乎是一个更大的类型 - 当然,在调试版本中,迭代器在该平台上非常大,以支持运行时有效性检查。

  

我没有警告/错误

那是因为你没有启用它们。在gcc上,-Wall(或只是-Wformat),我得到:

test.cpp:16:72: warning: format ‘%X’ expects argument of type ‘unsigned int’, but argument 2 has type ‘__gnu_cxx::__normal_iterator<Person*, std::vector<Person> >’ [-Wformat]
test.cpp:16:72: warning: format ‘%X’ expects argument of type ‘unsigned int’, but argument 3 has type ‘Person*’ [-Wformat]

告诉我到底出了什么问题。

答案 1 :(得分:7)

迭代器(包括std::vector<Person>::iterator,你作为printf()的参数传递)保证是POD,并且C风格的可变参数函数的参数可以只是POD。

  

WTF!?!我没有警告/错误

这是因为将非POD参数传递给C风格的可变参数函数是未定义的行为。编译器不需要发出诊断,尽管一些非常好的编译器会这样做(as correctly mentioned by Mark B in the comments)。

答案 2 :(得分:1)

使用"%X"格式说明符来格式化迭代器。 “Unsmart”使用&*的迭代器。

在gcc中,向量的迭代器通常是指针的包装器,具有相同的大小和布局。这就是为什么你可以将迭代器传递给printf并远离它。

在调试模式下的MSVC中,使用的调试迭代器包含的成员多于一个指针,并且它们的大小和布局不同。这就是您的代码在调试模式下与MSVC断开的原因。