[英]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.