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

0

Я нашел этот код в библиотеке рендеринга Quake 3. Существует такая функция:

void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap );'

Он вызывается в цикле еще что-то вроде этого:

R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse );

Странная часть состоит в том, что poly был объявлен как srfPoly_t *poly. Что здесь происходит? Он srfPoly_t объект srfPoly_t (void *) и затем surfaceType_t функцию в качестве объекта surfaceType_t.

Вот объявление для соответствующих структур:

typedef enum {
  SF_BAD,
  SF_SKIP,        // ignore
  SF_FACE,
  SF_GRID,
  SF_TRIANGLES,
  SF_POLY,
  SF_MD3,
  SF_MD4,
  SF_FLARE,
  SF_ENTITY,        // beams, rails, lightning, etc that can be determined by entity
  SF_DISPLAY_LIST,

  SF_NUM_SURFACE_TYPES,
  SF_MAX = 0x7fffffff     // ensures that sizeof( surfaceType_t ) == sizeof( int )
} surfaceType_t;

typedef struct srfPoly_s {
  surfaceType_t surfaceType;
  qhandle_t   hShader;
  int       fogIndex;
  int       numVerts;
  polyVert_t    *verts;
} srfPoly_t;

Это работает на C, но я пытаюсь реализовать что-то подобное в C++, но я получаю следующую ошибку:

Error   1   error C2664: 'int RefDef::AddDrawSurf(surfaceType_t *)' : cannot convert argument 1 from 'void *' to 'surfaceType_t *'

Казалось бы, я не могу выполнить этот тип приведения в C++, или, может быть, есть что-то еще, что я не могу понять. Я не очень хорошо знаком с C++ и хотел бы узнать, как настроить что-то подобное с этим.

Я предполагаю, что это имеет отношение к проверке типов в C++, поэтому это недопустимо. Как я могу реализовать что-то подобное в C++ безопасным способом?

  • 6
    По сути, это R_AddDrawSurf(&poly->surfaceType, ...) способ сделать R_AddDrawSurf(&poly->surfaceType, ...) . Без веской причины, которую я вижу. Адрес структуры также является адресом ее первого члена, поэтому звезды совпадают. Что касается того, почему он работает в C, но не в C ++: в C void* может быть неявно преобразован в любой тип указателя, а в C ++ - нет.
  • 4
    Это не приведение структуры к void* . Он приводит указатель структуры к void* .
Теги:

1 ответ

5
Лучший ответ

Это работает в C, потому что структуры - это просто блоки памяти с каждым элементом структуры, выложенным последовательно. Это действие работает, потому что первые n байтов структуры srfPoly_t состоят из перечисления surfaceType_t в этой структуре. srfPoly_t функция пытается интерпретировать переданный srfPoly_t как surfaceType_t и успешно, потому что первые n байтов аргумента являются, по сути, поверхностным surfaceType_t. Не делайте этого без уважительной причины.

Отбрасывание из void* не происходит автоматически в C++, как в C. Вы можете использовать reinterpret_cast для явного броска между двумя различными типами структур:

srfPoly_t* mySrfPoly_t;
surfaceType_t* mySurfaceType = reinterpret_cast<surfaceType_t*>(mySrfPoly_t);
  • 1
    Обратите внимание, что здесь вы создаете копию данных в mySrfPoly_t.surfaceType , а OP - после указателя на оригинал.
  • 2
    К сожалению, я забыл привести от указателя к указателю. Спасибо за улов - я отредактировал свой ответ, чтобы отразить это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню