Struct Hack

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

EditText of this page (last edited June 21, 2011) or FindPage with title or text search