Do data members form a range?
Asked Answered
E

5

16

Can I treat consecutive data members of the same type as a range? For example:

struct X
{
    int a, b, c, d, e;
};

X x = {42, 13, 97, 11, 31};

std::sort(&x.a, &x.a + 5);   // kosher?
Ebsen answered 5/9, 2013 at 12:11 Comment(7)
Wasn’t there a guarantee somewhere about this for PODs (i.e. trivial and standard layout), where all the members have the same type, that they could be treated as arrays?Fitful
Add a static_assert(sizeof(X) == 5*sizeof(int), "I've been a really bad girl").Ataraxia
sizeof(X) does not have to be exactly the size of 5 ints. If there is padding bytes at the end of the struct, the code could still do what it is expected to do.Thermoscope
@Zyx2000 What would be the point of padding if all fields are of the same type?Ebsen
@Zyx2000 that's why you should assert it.Ataraxia
@FredOverflow I don't know any particular reason, but I believe implementations are allowed to do that.Thermoscope
@R.MartinhoFernandes I meant that sizeof(X) does not have to be 5 ints for this trick to work.Thermoscope
D
15

No, this is undefined behaviour. You are treating x.a like the first element of an array, which it isn't. May work on some implementations, may raid your fridge too ;)

Devise answered 5/9, 2013 at 12:17 Comment(4)
Correct, but For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type. So you can treat it as a pointer to the first element of an array, just the length is one.Adjuvant
@JesseGood That quote allows X* p = &x; ++p; to get a pointer past the end, but not what's in OP.Roobbie
@Roobbie But for completeness: once you get said pointer to one past the end you can use it to refer to the second element if it is there. C++ doesn't care whence you get the pointer. Of course, if it's not there, you get the nasties.Ataraxia
@R.MartinhoFernandes I'm not sure what you mean. Is it there? Or is it not there?Ebsen
K
7

Don't do that. Compiler is free to add paddings between structure members(and at the end).

Knout answered 5/9, 2013 at 12:23 Comment(2)
What would be the point of padding if all fields are of the same type?Ebsen
@FredOverflow faster access in case the CPU does not have specialized load/store instructions or alignment restrictions.Libbielibbna
U
4

If this is really something you want to do, make it an array, vector or similar.

As others have said, the standard makes no guarantees about the members being stored without gaps or otherwise things that cause problems. (And to make matters worse, it will appear to work, until you compile it with a different (version of) compiler, or for another architecture some months or years later, and of course, it won't be easy to figure out what went wrong).

Unmusical answered 5/9, 2013 at 12:52 Comment(0)
G
2

No, this is not possible in C++. It would be rather difficult to standarize; in this case the semantic is simple enough, but what if the struct was heterogenous?

Grayce answered 5/9, 2013 at 12:17 Comment(0)
A
0

Generally, it's a bad idea. If you want to treat some variables as array, you should declare them as array :)

Nevertheless you can use some compiler-specific instruction to ensure that there is no padding between elements, f.i.:

#pragma pack(push, 1)  
struct X
{
    int a, b, c, d, e;
};
#pragma pack(pop)

or

struct  __attribute__((__packed__)) X
{
    int a, b, c, d, e;
};
Abreast answered 7/9, 2013 at 21:21 Comment(1)
Why would there be padding between integers (or any other data member of one type)?Ebsen

© 2022 - 2024 — McMap. All rights reserved.