значение указателя на элемент данных в переполнении стека

Встречайте очень странную проблему, кто-нибудь знает, в чем причина этого? код протестирован под Visual Studio 2012.

#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;
}

1

Решение

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

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 — указатель на функцию-член типа B, int C :: * p — указатель на функцию-член типа 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);
0

Другие решения

Указатели на участников — это не просто простые C-указатели, поэтому их передача printf на самом деле неопределенное поведение, потому что printf будет верить в "%p" и C-приведение указателя на член к void*,

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

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

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

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

2

По вопросам рекламы [email protected]