1

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

在 gcc我明白了。但在 MSVC 我得到

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

哇!?!我没有收到任何警告/错误。有谁愿意解释为什么最后两个值不是 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);
    }

}
4

3 回答 3

8

您将 avector::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]

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

于 2013-06-17T18:18:37.880 回答
7

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

哇!?!我没有收到任何警告/错误

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

于 2013-06-17T18:17:58.217 回答
1

您使用"%X"格式说明符来格式化迭代器。使用 . "Unsmart" 迭代器&*

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

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

于 2013-06-17T18:18:05.807 回答