PDA

View Full Version : [Tips - C] Grab bag of useful techniques with structs



Eris
08-24-2009, 03:52 PM
This works in C++ as well, but most of it can be done with classes instead. This is a set of work-arounds to get object-oriented features in C.

Arbitrary length structs:

You can use C's lack of bounds checking to create arrays that have arbitrary size.


struct foo {
int type;
char data[1];
};

/* ... */

struct foo *create_foo_with_length(int type, int data_length) {
/* One byte is always part of sizeof(struct foo). Add data_length - 1 to
compensate for the rest of the bytes */
return malloc(sizeof(struct foo) + data_length - 1);
}

/* ... */

void bar() {
struct foo *f = create_foo_with_length(TYPE_BAR, 100);
/* This is now valid: */
int i;
for(i = 0; i < 100; i++) {
f->data[i] = 2*i;
}
free(f);
}


This is common in network programming. You can construct a system that allows for data chunks of different size by reading the first few bytes corresponding to the type id, and then allocate the rest of the buffer size depending on the type.

Next technique is "struct inheritance":



struct base {
int type;
int p;
int q;
}
struct childA {
struct base base; /* Must be first element */
int r;
int s;
}

struct childB {
struct base base; /* Must be first element */
int t;
int u;
}


void bar() {
struct childA c;
struct childB c;
struct bar *a = (struct base *) &c;
struct bar *b = (struct base *) &c;
/* a and b are now a valid pointers of type c, corresponding to
a.child and b.child respectively. */
/* If the base struct has a field indicating it's type, you can use that to
indicate what sort of struct it is, and pointer cast to those types to access
their members in a valid fashion */

}

Shin Natsume
10-05-2009, 02:13 PM
I actually find this post to be useful. I've always heard talk of C having the ability to use OO features. However I still would prefer procedural over encapsulation anyday.

Shin Natsume
10-05-2009, 02:18 PM
Also, libnet allocates that memory behind the scenes >_> for the chunks of data.

Eris
10-05-2009, 02:26 PM
Here's another pretty neat trick:



int x;
if(foo) x = 1;
else if(bar) x = 2;
else if(baz) x = 3;
else x = 4;


Can also be written


x = foo ? 1 :
bar ? 2 :
baz ? 3 :
4;


Also works with returns and whatnot, and in any language that has the "test ? true : false" operator (C, C++, PHP I think, + other languages).