2013-08-29 5 views
1

Познакомьтесь с очень странной проблемой, кто-нибудь знает, в чем причина этого? код испытывается под Visual Studio 2012.значение указателя на элемент данных в C++

#include <iostream> 
struct A { 
    int a; 
}; 
struct B { 
    int b; 
}; 
struct C : public A, public B { 
    int c; 
}; 

int main() { 
    int C::*p = &C::b; 
    std::printf("%p\n", &C::b); //00000000 
    std::printf("%p\n", p);  //00000004 
    return 0; 
} 
+2

Указатели на член не только простые указатели, так что вы можете не только напечатайте их с помощью '% p' –

ответ

0

Обратите внимание, что, возможно, неожиданный результат:

printf("typeid(&C::b) = %s\n",typeid(&C::b).name()); 
printf("typeid(&B::b) = %s\n",typeid(&B::b).name()); 

Что на VS2010 урожайности:

typeid(&C::b) = int B::* 
typeid(&B::b) = int B::* 

Это указывает на то, что результирующий тип для & C :: b является указателем на тип B. Так как C является производным от B, указатель свободно конвертируется в указатель на тип C. Это объясняет разницу между двумя значениями, которые вы видите. & C :: б функция члена указатель на тип B, C INT :: * р является функция члена указателя на тип C.

int B::*p_b = &B::b; 
int C::*p_c = p_b; 
printf("p_b = %p\n", p_b); 
printf("p_c = %p\n", p_c); 
2

Указатели на члены не только простые C-указатели, так передавая их printf фактически неопределенное поведение, потому что printf поверю в "%p" и C-литой указатель -to-member до void*.

Только преобразования указателей на члены, разрешенных стандартом, перечислены в пункте 4.11:

  1. константы нуль-указатель может быть преобразован в нулевой указатель члена значений
  2. B::*T могут быть преобразованы в D::*T, если B является доступным, несимметричным и невиртуальным базовым классом D.

Указатели на членов могут иметь разные размеры в зависимости от классов, на которые они указывают.

Смотрите здесь для получения дополнительной информации о реализации указатель на член в MSVC: http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspx

+0

. Разберите код, и я обнаружил, что 0 выбрано как параметр для printf. Здесь нет броска. –

+0

Проблема с разборкой здесь заключается в том, что после того, как компилятор генерирует машинный код, вы потеряли всю информацию о типе, которая объясняет, почему номера являются такими, какие они есть. Скрытая часть в этом случае находится в части «int C :: * p = &C::b;», потому что она не делает то, что вы думаете, что она делает. – Speed8ump