我正在调试一些涉及指向成员字段的指针的代码,我决定将它们打印出来以查看它们的值。我有一个函数返回指向成员的指针:
#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
内的字段位置(即1
为y
而0
为x
),但不是,对于非空指针,打印值实际为1
,对于空指针,打印值为0
。我想这是符合标准的行为(即使它没有帮助) - 我是对的吗?此外,兼容的c ++实现是否可以始终打印0
指向成员的指针?甚至是空字符串?
最后,我如何以有意义的方式打印指向成员的指针?我想出了两个丑陋的方式:
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!
有更好的方法吗?
答案 0 :(得分:2)
指向会员的指针并不像您想象的那么简单。它们的大小从编译器到编译器以及从类到类的变化,具体取决于类是否具有虚方法以及它是否具有多重继承。假设它们是int大小不是正确的方法。你可以做的是用十六进制打印它们:
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
} // ()
但是,由于您不知道指针的结构以及每个字节(或几个字节)的含义,我不确定该信息对您有多大用处。
答案 1 :(得分: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';
}
答案 2 :(得分: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 ;
}
您收到有关违反严格的抗锯齿规则的警告(请参阅this link),但结果是您可能期望的结果:
0, 0x4, 0x8
然而,编译器可以自由地实现指向成员的指针功能,但是你不能依赖这些值是有意义的。
答案 3 :(得分:0)
我认为你应该使用printf
来解决这个问题
#include <stdio.h>
struct test{int x,y,z;}
int main(int argc, char* argv[])
{
printf("&test::x=%p\n", &test::x);
printf("&test::y=%p\n", &test::y);
printf("&test::z=%p\n", &test::z);
return 0;
}