2

メンバ フィールドへのポインタを含むいくつかのコードをデバッグしていたので、値を確認するためにそれらを出力することにしました。メンバーへのポインターを返す関数がありました。

#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
    switch (what) {
    case 0: return &test::x;
    case 1: return &test::y;
    case 2: return &test::z;
    default: return NULL;
    }
}

私は使用してみましたcout

#include <iostream>
int main()
{
    std::cout << select(0) << " and " << select(3) << '\n';
}

私は得1 and 0た。struct数字は(つまり is1yis 0)内のフィールドの位置を示していると思っていましたxが、実際には出力された値は1非 null ポインターと0null ポインター用です。これは標準に準拠した動作だと思います (役に立ちませんが) - そうですか? さらに、準拠した C++ 実装が常に0メンバーへのポインターを出力することは可能ですか? それとも空の文字列ですか?

最後に、意味のある方法でメンバーへのポインターを出力するにはどうすればよいですか? 私は2つの醜い方法を思いつきました:

printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?

ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!

より良い方法はありますか?

4

4 に答える 4

2

メンバーへのポインターは、思ったほど単純ではありません。それらのサイズは、クラスに仮想メソッドがあるかどうか、および多重継承があるかどうかに応じて、コンパイラごと、クラスごとに異なります。それらがintサイズであると仮定することは正しい方法ではありません。できることは、それらを 16 進数で出力することです。

void dumpByte(char i_byte)
{
    std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
    std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()

template <typename T>
void dumpStuff(T* i_pStuff)
{
    const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
    size_t size = sizeof(T);
    while (size)
    {
        dumpByte(*pStuff);
        ++pStuff;
        --size;
    } // while
} // ()

ただし、ポインターの構造と各バイト (または数バイト) の意味がわからないため、その情報がどの程度役立つかはわかりません。

于 2011-10-19T19:49:16.273 に答える
1

メンバーポインタは通常のポインタではありません。あなたが期待する過負荷<<は実際にはありません。

型のパンニングを気にしない場合は、何かをハックして実際の値を出力できます。

int main()
{
  ptr_to_member a = select(0), b = select(1);
  std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
            << *reinterpret_cast<uint32_t*>(&b) << " and "
            << sizeof(ptr_to_member) << '\n';
}
于 2011-10-19T19:45:31.663 に答える
0

これらのメンバーへのポインターの生の値は、次のように表示できます。

#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
    switch (what) {
    case 0: return &test::x;
    case 1: return &test::y;
    case 2: return &test::z;
    default: return NULL;
    }
}

int main()
  {
  ptr_to_member x = select(0) ;
  ptr_to_member y = select(1) ;
  ptr_to_member z = select(2) ;
  std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
  }

厳密なアンチエイリアシング ルールに違反しているという警告が表示されますが (このリンクを参照してください)、結果は次のようになります。

0, 0x4, 0x8

それにもかかわらず、コンパイラーはメンバーへのポインター機能を自由に実装できるため、これらの値が意味を持つことに依存することはできません。

于 2011-10-19T20:35:37.777 に答える