简体   繁体   中英

C/C++ Pointer to a POD struct also points to the 1st struct member

Can I assume that a C/C++ struct pointer will always point to the first member?
Example 1:

typedef struct {
 unsigned char  array_a[2];
 unsigned char  array_b[5];
}test;
//..
test var;
//..

In the above example will &var always point to array_a? Also in the above example is it possible to cast the pointer to an unsigned char pointer and access each byte separately?
Example 2:

function((unsigned char *)&var,sizeof(test));
//...
//...
void function(unsigned char *array, int len){
 int i;
 for( i=0; i<len; i++){
    array[i]++;
 }
}

Will that work correctly?

Note: I know that chars are byte aligned in a struct therefore I assume the size of the above struct is 7 bytes.

For C structs, yes, you can rely on it. This is how almost all "object orientated"-style APIs work in C (such as GObject and GTK).

For C++, you can rely on it only for "plain old data" (POD) types, which are guaranteed to be laid out in memory the same way as C structs. Exactly what constitutes a POD type is a little complicated and has changed between C++03 and C++11, but the crux of it is that if your type has any virtual functions then it's not a POD.

(In C++11 you can use std::is_pod to test at compile-time whether a struct is a POD type.)

EDIT: This tells you what constitutes a POD type in C++: http://en.cppreference.com/w/cpp/concept/PODType

EDIT2: Actually, in C++11, it doesn't need to be a POD, just "standard layout", which is a lightly weaker condition. Quoth section 9.2 [class.mem] paragraph 20 of the standard:

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [ Note: There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment. — end note ]

From the C99 standard section 6.7.2.1 bullet point 13:

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

The answer to your question is therefore yes.

Reference (see page 103)

The compiler is free to add padding and reorganize the struct how it sees fit. Especially in C++ you can add (virtual) functions and then chances are that the virtual table is hidden before that. But of course that are implementation details. For C this assumption is valid.

For C, it's largely implementation-specific, but in practice the rule (in the absence of #pragma pack or something likewise) is:

  • Struct members are stored in the order they are declared. (This is required by the C99 standard, as mentioned here earlier.)
  • If necessary, padding is added before each struct member, to ensure correct alignment.

So given a struct like

struct test{
char ch;
int i;
}

will have ch at offset 0, then a padding byte to align, i at offset 2 and then at the end, padding bytes are added to make the struct size a multiple of 8 bytes.(on a 64-bit machine, 4 byte alignment may be permitted in 32 bit machines)

So at least in this case, for C, I think you can assume that the struct pointer will point to the first array.

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