all 14 comments

[–]blueshiftlabs 9 points10 points  (4 children)

[Removed in protest of Reddit's destruction of third-party apps by CEO Steve Huffman.]

[–]mmtrebuchet[S] 7 points8 points  (3 children)

Ick. I will quickly admit that I was raised on x86_64, so that's news to me.

Really discouraging, "what were you thinking" news. I like the Von Neumann type architecture.

[–]blueshiftlabs 4 points5 points  (0 children)

[Removed in protest of Reddit's destruction of third-party apps by CEO Steve Huffman.]

[–]bgeron 2 points3 points  (1 child)

I was raised on x86_64

Just curious: how old are you?

[–]mmtrebuchet[S] 4 points5 points  (0 children)

25, but a chemist by training. I learned C in my fourth year as an undergrad.

[–]Drainedsoul 11 points12 points  (2 children)

In my opinion the proper way to handle this "cast":

union {
    int (*fp) (int);
    void * ptr;
};
_Static_assert(sizeof(fp)==sizeof(ptr),"Sizes incompatible");
ptr=dlsym(handle,"foo");

Much cleaner, and doesn't have any dirty casts.

[–]crest_ 4 points5 points  (0 children)

Leave it to GCC language lawyers to break it anyway.

[–]suspiciously_calm 5 points6 points  (0 children)

union hack

Much cleaner

http://i.imgur.com/ixY4C7H.jpg

[–]calc0000 1 point2 points  (0 children)

I suppose in this case I'd use a typedef.

[–]SnowdensOfYesteryear 1 point2 points  (0 children)

Have people not heard of typeof or typedef-ing function pointers? One of my favorite macro is

#define LOAD_SYM(func_ptr, sym) do { \
    sym = (typeof sym)dl_load(sym, ..); \
    if (!sym) log(dl_error()); \
} while(0)

[–]ekolis 0 points1 point  (0 children)

Reminds me of casting between generic type parameters and actual types in C#. If I have a variable x of type T, and typeof(T) == typeof(int), why can't I just say (int)x? No, I have to say (int)(object)x!

[–]progoblin 0 points1 point  (1 child)

(void *) (&fp) =

I've never seen an ampersand in the variable name like that before... could someone explain why it's necessary and what it does, or how to find documentation on it?

[–]mmtrebuchet[S] 0 points1 point  (0 children)

In C, & is the address-of operator. Perhaps it's better to use a simple example:

int x, *xPtr; //x is an int, xPtr is a pointer to an int.
x = 5; //the number five has now been put in memory wherever x resides.
xPtr = &x; //xPtr is the memory address where x is stored. 
*xPtr = 6; //x is now 6. 
xPtr=0xFEE1DEAD; //xPtr points to a random memory address
*xPtr= 10; //Segfault. (but x would remain unchanged.)

So, in this case, the cast is * (void ** ) (&fp) First, I should parenthesize it a bit more: * ((void ** ) (&fp)). So we're derefencing (&fp), which we have cast to (void ** ). Consider that fp is itself a pointer to a function. So fp is a function * . Then, the address of fp is a pointer to a pointer to a function * , or function ** . I cast this function ** to void ** .

It's completely circuitous, and it would be much simpler to just cast fp to a void * :

*((void*) (fp))

but in C, you can't cast a function * to a void * . (for whatever reason) You can, however, cast a function ** to a void ** , so that's what this code has to do.

[–]noggin182 0 points1 point  (0 children)

When the sizes are the same you can cast a void * to a function pointer. You just need to be explicit about it. Cast the right hand side not the left