Is this an alternative to C ++ for breaking structure?

Is the following valid C ++? This is an alternative way to realize a tail of variable length to a flat structure. In C, this is usually done with struct hack.

struct Str { Str(int c) : count(c) {} size_t count; Elem* data() { return (Elem*)(this + 1); } }; Str* str = (Str*)new char[sizeof(Str) + sizeof(Elem) * count]; new (str) Str(count); for (int i = 0; i < count; ++i) new (str->data() + i) Elem(); str->data()[0] = elem0; str->data()[1] = elem1; // etc... 

I ask about this in response to the following related question

+6
source share
2 answers

No, this is not true:

Elem may have different alignment than Str , so (reinterpret_) dropping Str+1 to Elem* may or may not give you a valid pointer, and acccessing may give undefined behavior.

But why do you need to do something like that?

+2
source

Acts in what sense? This is C ++ using C-like methods that imho are great, as long as the project requirements leave no other choice. If you ask if it will work, it will be until problems with data alignment lead to code crash (i.e. Not x86, for example, SPARC, etc.). C ++ behaves the same as C when accessing memory.

I tested it using the following modifications under gcc and VS, and it works:

 struct Elem { Elem() : x(0), t(0) { memset(c, 0, sizeof(c));} Elem(int v) : x(v), t(0) { memset(c, 0, sizeof(c));} Elem(const Elem &e) { *this = e; } Elem &operator=(const Elem &e) { if (this != &e) { memcpy(c, ec, sizeof(c)); x = ex; t = et; } return *this; } char c[21]; int x; char t; }; struct Str { Str(int c) : count(c) {} size_t count; Elem* data() { return (Elem*)(this + 1); } }; int count = 11; Str *str = (Str*)new char[sizeof(Str) + sizeof(Elem) * count]; new (str) Str(count); for (int i = 0; i < count; ++i) { new (str->data() + i) Elem(); str->data()[i] = Elem(i+1); } for (int i=0; i<str->count; i++) cout << "[" << i << "]: " << str->data()[i].x << endl; 

In addition, I added different members of different sizes to Str and Elem to force different additions and play with alignments (VS / some GCC: #pragma pack (...), GCC: __ attribute__ ((aligned (...)) ) and, __ attribute __ (packed)).

Please note that leveling is unsafe for all architectures. - Relevant question

0
source

Source: https://habr.com/ru/post/958849/


All Articles