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

1 c++ visual-c++

我期待addr addr 33 44addr可以是任何东西,两者都是一样的.

在gcc 我得到了.但在MSVC中,我得到了

8D3678 0 9257096 9257096
8D3678 0 9257104 9257104
8D3678 0 9257112 9257112
Run Code Online (Sandbox Code Playgroud)

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 8

你是一个合格vector::iteratorprintf说法,其中一个整数的预期.这给出了未定义的行为.(顺便说一下,将指针作为第二个参数传递也是如此;但这可能会给出您在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]
Run Code Online (Sandbox Code Playgroud)

告诉我究竟出了什么问题.


And*_*owl 7

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

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

这是因为将非POD参数传递给C风格的可变参数函数是 未定义的行为.编译器不需要发出诊断,尽管一些非常好的编译器会这样做(正如Mark B在评论中正确提到的那样).