Type casts in C and type safety-Collection of common programming errors

@Soroush, here’s an example that might help you better understand what’s going on behind the scenes:

#include 

int main(void)
{
    printf("begin\n");
    printf("loop\n");

    // declare a function pointer
    int (*loopPtr)();
    // set the function pointer to the current function
    loopPtr = main;
    // skip over the first printf();
    loopPtr += 22;
    // call the new location
    loopPtr();
}

For me, it works on x86_64 when compiled with clang -O0 (well, it works until the stack is exhausted since this is infinite recursion and each function call chews through stack space).

I determined the offset 22 by compiling, then disassembling and subtracting the address of the start of main() from the address of the second printf().

First, I compiled it:

clang -O0 test.c

Then disassembled it:

otool -tv a.out

…which produced this output:

[...]
_main:
0000000100000ee0    pushq   %rbp
0000000100000ee1    movq    %rsp,%rbp
0000000100000ee4    subq    $0x20,%rsp
0000000100000ee8    leaq    0x00000073(%rip),%rdi
0000000100000eef    movb    $0x00,%al
0000000100000ef1    callq   0x100000f40
0000000100000ef6    leaq    0x0000006c(%rip),%rdi
0000000100000efd    movl    %eax,0xf4(%rbp)
0000000100000f00    movb    $0x00,%al
0000000100000f02    callq   0x100000f40
[...]

_main: indicates the entrypoint of the main() function, whose first address is 0x100000ee0. The first callq instruction corresponds with the first printf() call, which I want to skip, so I chose the address just after that: 0x100000ef6. 0x100000ef6 minus 0x100000ee0 is 22 decimal.

Originally posted 2013-11-09 23:34:32.