繁体   English   中英

为什么printf和std :: cout的输出不同?

[英]Why are the outputs of printf and std::cout different?

我尝试了以下C ++代码。 但是, printfstd::cout的输出是不同的。 为什么?

struct Foo
{
    int a;
    int b;
    int c;
};

int main()
{
    printf("%d\n", &Foo::c);  // The output is 8
    std::cout << &Foo::c << "\n"; // The output is 1
}

printf("%d\\n", &Foo::c) :这是未定义的行为,因为&Foo::c不是整数,而是指向成员的指针(但实际上,编译器通常存储指向数据的指针成员的偏移量,并且8Foo::c的偏移量,则输出8 )。

std::cout << &Foo::c :这将打印值&Foo::c 由于iostream没有指向成员打印机的指针,因此它选择最接近的成员:将其转换为bool ,并将其打印为整数。 因为&Foo::c转换为booltrue ,所以将打印1

输出是不同的,因为您的printf的行为是不确定的。

指向成员的指针(如&Foo::c产生的指针)不是整数。 printf函数需要一个整数,因为您也使用%d说明符告诉了它。

您可以通过在bool添加演员表来修改它,如下所示:

printf("%d\n", (bool)&Foo::c)

指向成员的指针可能会转换为布尔型(您可以使用强制转换),然后bool会成为可变参数的完整可变参数,因此将整数进行整数提升为int

说到bool转换,正是通过尝试调用std::ostreamoperator<<隐式地应用了转换。 由于不存在支持成员指针的运算符的重载,因此重载解析会在将&Foo::c隐式转换为布尔值之后选择另一个可调用的。

除了关于为什么编译器以这种方式解释代码的更确切的答案之外:您似乎还有一个XY问题您正试图将一个指向成员的指针格式化为整数,这强烈表明您打算做某事不同。

如果您想要的是存储在.cint值,则需要创建一个实例Foo some_foo; 并使用some_foo.c ,否则您需要将Foo::c声明为static成员,因此整个类中只有一个明确的Foo::c 在这种情况下,请勿使用该地址。

如果您想要获取某个Foo.c成员的地址,则应按照上述步骤进行操作,以使Foo::cstatic并引用一个特定变量,或者声明一个实例并采用其.c成员,然后取地址。 对象指针的正确printf()说明符为%p ,并使用<iostream>打印对象指针表示形式,将其转换为void*

printf( "%p\n", &some_foo.c );
std::cout << static_cast<void*>{&some_foo.c} << '\n';

如果想要的是类FooFoo::c的偏移量,则需要<stddef.h>offsetof()宏。 由于它的返回值是size_t ,与64位平台上的int大小不同,因此您可能希望显式转换结果或将printf()传递给z类型说明符:

#include <stddef.h>

/* ... */

  constexpr size_t offset_c = offsetof( Foo, c );
  printf( "%zu\n", offset_c );
  cout << offset_c << '\n';

无论您尝试做什么,如果编译器没有警告您类型不匹配,您都应该打开更多警告。 对于经过反复试验直到程序编译的人来说尤其如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM