Page 1 of 1

C

Posted: Wed Feb 02, 2005 6:19 am
by Balroj
Hi,

i've got some trouble with 2 c code:

Code: Select all

typedef void (*syscall_func)(void);
i can't understand what it's been defined with that. what's the use of de last (void) ?

Code: Select all

static union header {
struct {
    union header *link;
    unsigned size;
} s;
    union align {
      double d; unsigned u; void (*f)(void);
} x;
} freelist = { &freelist, 0 }, *freep = &freelist;
This one is taken from the the pdf in osdever.net. Can anyone explainme that?


Thanks far all.

Re:C

Posted: Wed Feb 02, 2005 6:32 am
by AR

Code: Select all

typedef void (*syscall_func)(void);
This is a function pointer, the void represents the arguments the function takes (ie. none). I assume you're referring to the function pointer again in the second one as well.

Here's a demonstration of a function pointer:

Code: Select all

#include <stdio.h>

int SayHello(int A, int B)
{
     printf("Hello, A=%i B=%i\n", A, B);
     return 67;
}

int SayHello2(int X, int Y)
{
     printf("Hello from SayHello2, X=%i Y=%i\n", X, Y);
     return 89;
}

//This declares a type called "HelloFunc" which represents a pointer to a function the takes 2 ints and returns an int
typedef int (*HelloFunc)(int,int);

int main()
{
     HelloFunc h = SayHello;   //Set the function pointer
     int r = h(6, 9);    //Call it
     printf("HelloFunc Function Pointer returned %i", r);

     h = SayHello2;    //Change the pointer
     r = h(90, 198);   //Call it again
     printf("HelloFunc Function Pointer returned %i", r);
     return 0;
}

Re:C

Posted: Wed Feb 02, 2005 7:41 am
by Solar

Code: Select all

static union header {
Declare a [tt]static union[/tt] (i.e., a union without external linkage) called "header".

A union is a datatype that can hold either of the declared datatypes. That means, while...

Code: Select all

struct foo
{
   int x;
   float f;
};
...can hold an [tt]int[/tt] and a [tt]float[/tt], ...

Code: Select all

union foo
{
   int x;
   float f;
};
...can hold an [tt]int[/tt] or a [tt]float[/tt], depending on whether you last wrote to [tt]foo.x[/tt] or [tt]foo.f[/tt].

Code: Select all

struct {
    union header *link;
    unsigned size;
} s;
"s" is the one possible content of an "header union", with "s" consisting of a "pointer to header union" named "link" (i.e., pointer to next "header" most likely), and an unsigned integer named "size".

Code: Select all

union align {
      double d; unsigned u; void (*f)(void);
} x;
"x" is the other possible content of an "header union", being a union itself holding either:
  • a double,
  • an unsigned int,
  • a pointer to a function accepting no arguments and not returning a value.

Code: Select all

} freelist = { &freelist, 0 }, *freep = &freelist;
One object of type "header union" is declared, named "freelist", with [tt]freelist.s.link[/tt] initialized with a pointer to "freelist" itself, and [tt]freelist.s.size[/tt] initialized to zero.

Afterwards, a "pointer to header union" is declared, named "freep", and initialized to point to the [tt]freelist[/tt] object we just initialized.

And while I'm at it, code like this - with lots and lots of unions, implicit initialization and comma operators, but lacking liberal comments - does ring every alarm bell in my head, for it seems someone really enjoyed his l33t sk1llz at writing l33t code. 8)

Re:C

Posted: Wed Feb 02, 2005 5:08 pm
by Balroj
thanks Solar and AR,

what's the really use of union? I mean, what's the diference/use betwen declare an union:

Code: Select all

union d
{
    int a;
    char b;
}
and declare 2 different variables:

Code: Select all

int a
char b;
Thanks for all

Re:C

Posted: Wed Feb 02, 2005 7:16 pm
by Curufir
The union will take up less space. It only has to allocate for the integer, because that is the longest variable. With the two separate variables memory must be allocated for both.

Solar is right IMHO, unions are hackish and will get you in all sorts of trouble very quickly.

Re:C

Posted: Thu Feb 03, 2005 2:40 am
by Solar
Curufir wrote: The union will take up less space. It only has to allocate for the integer, because that is the longest variable. With the two separate variables memory must be allocated for both.
You can also refer to two different data structures with one and the same pointer type, which can make sense in low-level list handling code. But it's a dangerous game - all too easily you've written one value and read the other, which is a bi*ch to debug.

It's a hardcore C coder's idea of mimicking C++ polymorphism, and even C++ coders customarily get it wrong the first time around.

Re:C

Posted: Wed Mar 02, 2005 4:41 pm
by Just another guest
A use I can think of for a union is to do something like this:

Code: Select all

union reg
{
  struct w
  {
    short low;
    short high;
  }
  long full;
}
or however it would be written properly (there's probably some bad syntax there, but I'm too lazy to make it perfect). Also, if you wanted it to be portable across CPUs with different endiness, you'd want some defines or something to order the highs and lows correctly.

Re:C

Posted: Thu Mar 03, 2005 1:47 am
by Schol-R-LEA
There are several kinds of data structures - especially in binary file formats - where the effective type of one variable depends on the value of another variable in the same data structure. This is what is called a 'discriminated union' (or a 'variant record' in Pascal and it's descendants), and while they are generally better avoided (especially since, as Solar correctly points out, polymorphism will usually work better), there are times when it is useful, mostly when dealing with the same sorts of old and/or proprietary data formats which rely heavily on bit fields.

As Just Another Guest points out, it can also be used for manipulating partial values of larger variables, or conversely, for 'packing' small values into one larger one.

They also open a hole in the type system which can be exploited for all kinds of weird bit-fiddling purposes, but to be honest you really don't want to go there unless you absolutely have to.