简体   繁体   中英

What type of C++ cast should be used to cast a pointer to a struct to its first member?

X is defined as the following:

struct X
{
    Y y;
    // more fields...
    int a;
};

I have a variable of type X . However, I would like to cast it to the type of its first member, in order to pass that into a function. I know that the C Standard permits it (and I suppose the C++ one does so as well).

In C I would do it like so:

X x;
Y* y = (Y*) x;
doStuff(y);

What type of cast is the right one in C++ for this? static_cast or reinterpret_cast ?

None.

You can't mess around with objects using pointers like that. C++ is not C, and these are not "just bytes" (contrary to popular belief).

And you don't need to!

Pass &x.y instead; it's already the Y* you want.

I'd always recommend using static_cast instead of reinterpret_cast in any situation where the static_cast isn't rejected by the compiler. If possible try to avoid doing any casting at all - in this case you probably want: Y* y = &x.y .

To answer the comment:

In this case, I have a PROCESS_MEMORY_COUNTERS_EX variable. However the WinAPI function GetProcessMemoryInfo takes a PROCESS_MEMORY_COUNTERS*. The former type starts with the exact same fields as the latter, and adds a few at the end. The intended usage is to pass into the function a pointer to the latter type, even if we hold a pointer to the former (larger) type.

The documentation for GetProcessMemoryInfo() states that the second parameter is:

A pointer to the PROCESS_MEMORY_COUNTERS or PROCESS_MEMORY_COUNTERS_EX structure that receives information about the memory usage of the process.

The Win32 API is a C API, and not a C++ one, so you can just use a C style cast here, or preferably a reinterpret_cast to make your intention clearer. I'd expect static_cast to be rejected by the compiler in this case. Note that the third cb parameter is there to tell the function which type of structure you actually provided - it should be set to either sizeof(PROCESS_MEMORY_COUNTERS) or sizeof(PROCESS_MEMORY_COUNTERS_EX) .

@FredLarson In this case, I have a PROCESS_MEMORY_COUNTERS_EX variable. However the WinAPI function GetProcessMemoryInfo takes a PROCESS_MEMORY_COUNTERS*. The former type starts with the exact same fields as the latter , and adds a few at the end. The intended usage is to pass into the function a pointer to the latter type, even if we hold a pointer to the former (larger) type.

The cleanest way to accomplish that would be probably (ab)using inheritance. This way, you can have your _EX type share members with the base type while actually being an instance of it.

struct X {
  int a;
  int b;
};

struct X_EX : public X {
  int other_member;
};

void doStuff(X*);

void foo(X_EX* ptr) {
 doStuff(ptr);
}

However, do note that "Inherit-to-extend" is seen as a code smell, and something to avoid if possible nowadays. I'd make sure to put a comment explaining why it's necessary here.

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