A
CeeLanguage coding trick where you make a struct
struct Hack {
TypeA A;
TypeB B;
char VariableArray[1];
};
Then when you actually allocate memory you use
struct Hack *aHack = malloc( sizeof(*aHack) - 1 + ARRAY_SIZE );
Then you just reference the out-of-bounds part of the array such that you
stay inside the memory actually allocated.
This qualifies as rude but effective in certain situations. Hence its name.
For more fun, some compilers allow you to declare a 0-length array, thus simplifying the allocation.
That's legal in CeePlusPlus. You are guaranteed to get a unique array every time.
I have long used this venerable and effective technique as a demonstration of why
StrongTyping is so over-rated as anything other than a hinting mechanism for developers. I think it illustrates the best and worst aspects of
CeeLanguage's "strong" typing mechanism.
I'm accustomed to using it in situations where we needed to allocate groups of objects (each with fixed- and variable-sized parts) and knew more than the compiler about how they should fit together.
--
TomStambaugh
Neither
CeeLanguage nor
CeePlusPlus has a
StrongTyping mechanism.
The
StructHack could be expressed in a
TypeSafe way with, e.g.,
struct Hack {
TypeA A;
TypeB B;
int l;
char VariableArray[l];
};
if this were allowed. Granted,
TypeChecking in such a setting is difficult.
See also
TuringEquivalencyForDataStructures.
The "
StructHack" is now officially supported by the C9X standard. The last member of a struct may have an incomplete array type. E.g., a struct may be declared as:
struct S {
int n;
double d[];
};
and used as:
struct S *sp = malloc( sizeof(struct S) + 4 * sizeof(double) );
So sp is equivalent to a pointer to the structure.
struct S' {
int n;
double d[4];
};
This trick only works if there is only 1 variable-sized component, and it is the last one in your structure.
If you need more than one variable-sized sub-component in your structure
(or if the "'out-of-bound' references" makes you feel uneasy),
you might prefer something more like this:
struct employee {
TypeA A;
TypeB B;
char * firstname;
char * lastname;
};
Then when you actually allocate memory you use
struct employee *an_employee = malloc( sizeof(*an_employee) );
an_employee.firstname = malloc( strlen(temp_first_name)+1 );
an_employee.lastname = malloc( strlen(temp_last_name)+1 );
strcpy( an_employee.firstname, temp_first_name);
strcpy( an_employee.lastname , temp_last_name);
CategoryCee,
CategoryLanguageTyping