简体   繁体   中英

Understanding casting a struct as a void pointer

I found this code in the rendering library for Quake 3. There is this function:

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

It is being called in a loop somehwere else like this:

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

The weird part is that poly was declared as srfPoly_t *poly . What is going on here? It is casting a srfPoly_t object to (void *) and then entering the function as a surfaceType_t object.

Here are the declaration for the relevant structs:

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;

This is working in C, but I am trying to implement something similar in C++, but I get the following error:

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

It would appear I cannot perform this type of cast in C++, or maybe there is something else I am unable to understand. I am not very familiar with C++ and would love to figure out how to set up something similar using it.

I am assuming this has something to do with type checking in C++, so it is not allowed. How can I implement something similar in C++ in a safe way?

This works in C because structs are simply blocks of memory with each element in the struct laid out consecutively. This cast works because the first n bytes of a srfPoly_t struct consist of the surfaceType_t enum within that struct. The called function tries to interpret the passed-in srfPoly_t as a surfaceType_t , and succeeds because the first n bytes of the argument are, in fact, a surfaceType_t . Do not do this without a very good reason.

Casts from void* 's do not automatically occur in C++ as they do in C. You can use reinterpret_cast to explicitly cast between two different types of structs:

srfPoly_t* mySrfPoly_t;
surfaceType_t* mySurfaceType = reinterpret_cast<surfaceType_t*>(mySrfPoly_t);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM