簡體   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