📄 ptrmem.c
字号:
// Special g++ Options: -fno-strict-aliasing// Origin: Mark Mitchell <mark@codesourcery.com>/* Generally, the lowest bit of the ptr is used to indicate whether a ptr-to-mem-func points to a virtual or a non-virtual member function. However, some platforms use all bits to encode a function pointer. Such platforms use the lowest bit of the delta, that is shifted left by one bit. */#if defined __MN10300__ || defined __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__#define ADJUST_PTRFN(func, virt) ((void (*)())(func))#define ADJUST_DELTA(delta, virt) (((delta) << 1) + !!(virt))#else#define ADJUST_PTRFN(func, virt) ((void (*)())((ptrdiff_t)(func) + !!(virt)))#define ADJUST_DELTA(delta, virt) (delta)#endif/* IA64 uses function descriptors instead of function pointers in its vtables, which means that we can't meaningfully compare them directly. */#if defined __ia64__#define CMP_PTRFN(A, B) (*(void **)(A) == *(void **)(B))#define VPTE_SIZE (16)#else#define CMP_PTRFN(A, B) ((A) == (B))#define VPTE_SIZE sizeof(void *)#endif#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100// Check that pointers-to-member functions are represented correctly.#include <cstddef>struct S{ int i; int j;};// Because S does not have a VPTR, it will not be a primary base of T,// and will therefore end up at a nonzero offset.struct T : public S { void f () {} virtual void g () {} virtual void h () {}};// Provide access to the raw function pointers. This is// mangling-dependent.extern "C" void _ZN1T1fEv ();extern "C" void _ZN1T1gEv ();extern "C" void _ZN1T1hEv ();// This structure is a C representation of a pointer-to-member.struct ptrmemfunc { void (*ptr) (); ptrdiff_t adj;};typedef int S::*sdp;typedef void (S::*sp)();typedef void (T::*tp)();intmain (){ S s; T t; sp x; tp y; ptrmemfunc *xp = (ptrmemfunc *) &x; ptrmemfunc *yp = (ptrmemfunc *) &y; ptrdiff_t delta = ((char *) &t) - ((char*) (S*) (&t)); // Pointers-to-function-members should have the same size and // alignment as the PTRMEMFUNC type. if (sizeof (sp) != sizeof (ptrmemfunc)) return 1; if (__alignof__ (sp) != __alignof__ (ptrmemfunc)) return 2; // The NULL pointer-to-member should have a NULL first PTR field. x = 0; if (xp->ptr != 0) return 3; y = x; if (yp->ptr != 0) return 4; // A non-virtual function should have a pointer to the function. // There should be no adjustment for the `T' version, and an // appropriate adjustment for the `S' version. y = &T::f; if (! CMP_PTRFN (yp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0))) return 5; if (yp->adj != ADJUST_DELTA (0, 0)) return 6; x = (sp) y; if (! CMP_PTRFN (xp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0))) return 7; if (xp->adj != ADJUST_DELTA (delta, 0)) return 8; // For a virtual function, we should see the vtable offset, plus // one. `T::h' is in the second slot: the vtable pointer points to // the first virtual function. y = &T::h; if (yp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1)) return 9; if (yp->adj != ADJUST_DELTA (0, 1)) return 10; x = (sp) y; if (xp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1)) return 11; if (xp->adj != ADJUST_DELTA (delta, 1)) return 12; // Pointers-to-data-members should have the same size and alignment // as a ptrdiff_t. if (sizeof (sdp) != sizeof (ptrdiff_t)) return 13; if (__alignof__ (sdp) != __alignof__ (ptrdiff_t)) return 14; // The value of a pointer-to-data member should be the offset from // the start of the structure. sdp z = &S::j; if ((char *) &s.j - (char *) &s != *((ptrdiff_t *) &z)) return 15; z = 0; if (*((ptrdiff_t *) &z) != -1) return 16;}#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */int main () {}#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -