我期待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);
}
}
答案 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断开的原因。