Valid in what sense? It is C++ using C-like techniques which imho is fine as long as the project requirements leave no other choice.
If you are asking if it will work, it will as long as data alignment issues do not crash the code (i.e. non x86 like SPARC, etc). C++ behaves much like C when addressing 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, e.c, sizeof(c));
x = e.x;
t = e.t;
}
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;
Also, I added various different size members to Str and Elem to force different padding and played with alignments (VS/some GCC: #pragma pack(...), GCC: __ attribute__ ((aligned (...))) and , __ attribute__(packed) ).
Please note that playing with alignments is not safe on all architectures - Relevant question