Tuesday, June 21, 2005

Returning structs in C functions

- Introduction


Well this is quite a "myth" for me, or it was.
When some people told me that was possible to return some structure from a C function i couldn't believe it.
I always heard that you need pointers, mallocs and stuff and now it's so simple.
So i'm here to demystify this "myth" :P

- Basic structs stuff

As you know, we can define some elaborated data types with C using the keyword struct properly.
Here is a simple example.

I will define some type Point representing x & y coordinates.
struct Point
{
int x;
int y;
};

Then I will define a function that will print some Point to the stdout.
void
printPoint (struct Point p)
{
printf ("x = %d ; y = %d\n", p.x, p.y);
}

Some main example.
int
main ()
{
struct Point p1;
p1.x = 2;
p1.x = 3;
printPoint (p1);
}

As you can see, this is the simplest example that i could give.

- The real thing

After this little introduction lets begin our dismystifying :)
I will now, create the function that will return our data type Point.
Point
newPoint (int x, int y)
{
Point ret;
ret.x = x;
ret.y = y;
return ret;
}

As you can see it is so easy that it's dificult to believe.
We create a Point called ret, assign its attributes and then return it as we wish.
Below there is some code that will demonstrate that this work.

Code here

- Aren't those structures too simple ?

Well i think now, you are conviced that this work.
But will it work with more anoying structs that have lots of stuff ??!
Really I don't know. I think so. If it works with this simple i think that i will work too with more realistic structures that you are using in your applications.
The next example is just the same of the above but with a little difference: Let's name our points.

Code here

As you can see it works fine just as we were expecting.

- Structs with structs inside.

This is a good approach.
We probably wanna have some complex struct that includes other structs.
Should this work too ? I guess so.

As you can see bellow i'll create the data type Line that will contain 2 Points.
typedef struct
{
Point orig;
Point dest;
} Line;


Now i will make it's constructor ( OO speaking :P )
Line
newLine (Point orig, Point dest)
{
Line ret;
ret.orig = orig;
ret.dest = dest;
return ret;
}

and, the correspondent print function.
void
printLine (Line l)
{
printf("Origin -> ");
printPoint(l.orig);
printf("Destiny -> ");
printPoint(l.dest);
}


Now runing test4() ....
void
test4 ()
{
printLine(newLine(newPoint(1,1,"Start"),newPoint(3,3,"End")));
}

and voilla ,
Origin -> Start : x = 1 ; y = 1
Destiny -> End : x = 3 ; y = 3

Code here
Now i can say that this should work with your complex-mega-uber-leet data structures ;)

- How does this stuff work ?

Now that we already know that this stuff works let's get some answers ;)
Probably your compiler has this behaviour.
A structure or union which is 1, 2, 4 or 8 bytes long is returned like a scalar.
A structure or union with any other size is stored into an address supplied by the caller (usually in a special, fixed register, but on some machines it is passed on the stack).
You can get more detailed information reading "further documentation".

- Conclusion

As we saw, this is possible. It's a way to return structures just like any other.
Surely this is simply and our code is clean and much more readable, but if this structs are very large this method is less eficient than returning a pointer to some structure.

- Further Documentation


- Mail me

If you have any questions, comments or suggestions feel free to contact me at : sfbs_@mega.ist.utl.pt (without the _ at sfbs_).

./configure && make && make install

Hi guys!
Well this is my first blog about this science that i love , computer science!
Here we'll discuss and share all kind of information, news, comments, what is going on in our particulary world. I would aprecciate further comments and also some good discussion on what matters ;)
Stay cool,

I'm waiting for you.