[英]Why are the outputs of printf and std::cout different?
我尝试了以下C ++代码。 但是, printf
和std::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
不是整数,而是指向成员的指针(但实际上,编译器通常存储指向数据的指针成员的偏移量,并且8
是Foo::c
的偏移量,则输出8
)。
std::cout << &Foo::c
:这将打印值&Foo::c
。 由于iostream没有指向成员打印机的指针,因此它选择最接近的成员:将其转换为bool
,并将其打印为整数。 因为&Foo::c
转换为bool
为true
,所以将打印1
。
输出是不同的,因为您的printf
的行为是不确定的。
指向成员的指针(如&Foo::c
产生的指针)不是整数。 printf
函数需要一个整数,因为您也使用%d
说明符告诉了它。
您可以通过在bool
添加演员表来修改它,如下所示:
printf("%d\n", (bool)&Foo::c)
指向成员的指针可能会转换为布尔型(您可以使用强制转换),然后bool
会成为可变参数的完整可变参数,因此将整数进行整数提升为int
。
说到bool
转换,正是通过尝试调用std::ostream
的operator<<
隐式地应用了转换。 由于不存在支持成员指针的运算符的重载,因此重载解析会在将&Foo::c
隐式转换为布尔值之后选择另一个可调用的。
除了关于为什么编译器以这种方式解释代码的更确切的答案之外:您似乎还有一个XY问题您正试图将一个指向成员的指针格式化为整数,这强烈表明您打算做某事不同。
如果您想要的是存储在.c
的int
值,则需要创建一个实例Foo some_foo;
并使用some_foo.c
,否则您需要将Foo::c
声明为static
成员,因此整个类中只有一个明确的Foo::c
。 在这种情况下,请勿使用该地址。
如果您想要获取某个Foo
的.c
成员的地址,则应按照上述步骤进行操作,以使Foo::c
是static
并引用一个特定变量,或者声明一个实例并采用其.c
成员,然后取地址。 对象指针的正确printf()
说明符为%p
,并使用<iostream>
打印对象指针表示形式,将其转换为void*
:
printf( "%p\n", &some_foo.c );
std::cout << static_cast<void*>{&some_foo.c} << '\n';
如果想要的是类Foo
中Foo::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.