Как я могу преодолеть «ошибку C2100: недопустимое косвенное обращение» при доступе к содержимому void * в VS2008 - PullRequest
4 голосов
/ 15 октября 2008

У меня есть приложение C, которое я создал в VS2008. Я создаю фиктивную функцию создания, которая переопределяет ссылки на функции в структуре. Однако, если я попытаюсь сделать это прямым способом с чем-то вроде:

void *ptr = &(*env)->GetVersion;
*ptr = <address of new function>

тогда я получаю сообщение об ошибке «C2100: недопустимое косвенное обращение» в виде * ptr, когда ptr является недействительным *, кажется, запрещенной конструкцией Я могу обойти это, используя указатель int / long, сопоставив его с тем же адресом и изменив содержимое длинного указателя:

*structOffsetPointer = &(*env)->GetVersion;
functionPointer = thisGetVersion;
structOffsetPointerAsLong = (long *)structOffsetPointer;
*structOffsetPointerAsLong = (long)functionPointer;

но я обеспокоен тем, что использование указателей long или int вызовет проблемы при переключении между 32 и 64-битными средами.

Так есть ли простой способ отключить эту ошибку? Если нет, то есть ли int или long 64 бита под win64?

Ответы [ 4 ]

4 голосов
/ 15 октября 2008

При разыменовании «void *» вы остаетесь с «void», который не имеет размера (или действительно не имеет типа в этом отношении), поэтому он не знает, как что-то присвоить ему. Это так же, как:

void blah = 0xdeadbabe; // let's assume a 32-bit addressing system

Чтобы добавить свой ответ и дать решение, я бы дал ему правильный тип указателя на функцию типа GetVersion. Если GetVersion, на который указывает ваше поле структуры env, имеет вид:

int GetVersion();

тогда вы хотите:

int (**ptr)() = &(*env)->GetVersion;
3 голосов
/ 15 октября 2008

Тогда как насчет:

void **ptr = (void **) &(*env)->GetVersion;
*ptr = <address of new function>

Правильный способ сделать это - работать с системой типов, избегать всех приведений и объявлять фактические указатели на такие функции:

typedef int (*fncPtr)(void);
fncPtr *ptr = &(*env)->GetVersion;
*ptr = NewFunction;

Выше предполагается, что GetVersion имеет тип fncPtr, а NewFunction объявлена ​​как int NewFunction (void);

1 голос
/ 15 октября 2008

Как уже упоминалось, чтобы сохранить адрес функции в указателе, вы просто не должны делать косвенное указание.

Тем не менее, вы также говорите о том, что беспокоитесь о размере типа int, на который вы можете хранить указатель (что обычно не то, что вы хотите делать, если у вас нет действительно веской причины).

Если по какой-то причине вы хотите удерживать указатель в типе int, то в Windows тип UINT_PTR (или uintptr_t из stdint.h, если он у вас есть) будет содержать большинство типов указателей (я не думаю, он достаточно большой, чтобы содержать некоторые типы указателей на члены).

1 голос
/ 15 октября 2008

В прошлый раз, когда я играл с void * & C под визуальной студией, VS играл не очень хорошо. Вот некоторые информационные данные:

Указатель всегда имеет размер системного слова (16.08.32) (... если у вас нет сегментированной памяти, которую я предполагаю , которой у вас нет) Это потому, что он должен указывать на любую область памяти. Для машины von Neumann указатель функции будет того же размера, что и указатель данных, поскольку данные и код занимают одно и то же пространство памяти. Это не гарантируется архитектурой Harvard . Я не достаточно знаком с Windows Vista, чтобы знать, программно ли она подделывает гарвардскую архитектуру по соображениям безопасности.

Лично я бы не отключил бы эту ошибку, просто чтобы компилятор выполнил свою работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...