views:

120

answers:

5

So lets say I have this code

int my_static_int = 4;
func(&my_static_int);

I passed the function a pointer to my_static_int, obviously. But what happens when the code is compiled? Avenue I've considered:

1) When you declare a non-pointer variable, C automatically creates its pointer and does something internally like typedefs my_static_int to be *(internal_reference)

Anyway, I hope that my question is descriptive enough

+4  A: 

Pointers are just a term to help us humans understand what's going on.

The & operator when used with a variable simply means address of. No "pointer" is created at runtime, you are simply passing in the address of the variable into the function.

If you have:

int x = 3;
int* p = &x;

Then p is a variable which holds a memory address. Inside that memory address is an int.

Brian R. Bondy
A: 

Why not look at the assembly output? You can do this with gcc using the -S option, or (if your system uses the GNU toolchain) using the objdump -d command on the resulting object file or executable file.

R..
+1  A: 

When the code is compiled, function func receives the address of your my_static_int variable as parameter. Nothing else.

There no need to create any implicit pointers when you declare a non-pointer variable. It is not clear from your question how you came to this weird idea.

AndreyT
+2  A: 

If you really want to know how the code looks under the covers, you have to get the compiler to generate the assembler code (gcc can do this with the -S option).

When you truly grok C and pointers at their deepest level, you'll realise that it's just the address of the variable being passed in rather than the value of the variable. There's no need for creating extra memory to hold a pointer since the pointer is moved directly from the code to the stack (the address will probably have been set either at link time or load time, not run time).

There's also no need for internal type creation since the compiled code already knows the type and how to manipulate it.

Keeping in mind that this is implementation-specific, consider the following code:

int my_static_int = 4;
static void func (int *x) {
    *x = *x + 7;
}
int main (void) {
    func(&my_static_int);
    return 0;
}

which, when compiled with gcc -S to get the assembler, produces:

        .file   "qq.c"
.globl _my_static_int
        .data
        .align 4
_my_static_int:
        .long   4
        .text
        .def    _func;  .scl    3;      .type   32;     .endef
_func:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        movl    8(%ebp), %edx
        movl    (%edx), %edx
        addl    $7, %edx
        movl    %edx, (%eax)
        popl    %ebp
        ret
        .def    ___main;        .scl    2;      .type   32;     .endef
.globl _main
        .def    _main;  .scl    2;      .type   32;     .endef
_main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        addl    $15, %eax
        addl    $15, %eax
        shrl    $4, %eax
        sall    $4, %eax
        movl    %eax, -4(%ebp)
        movl    -4(%ebp), %eax
        call    __alloca
        call    ___main
        movl    $_my_static_int, (%esp)
        call    _func
        movl    $0, %eax
        leave
        ret

The important bit is these sections:

movl    $_my_static_int, (%esp)  ; load address of variable onto stack.
call    _func                    ; call the function.
:
movl    8(%ebp), %eax  ; get passed parameter (the address of the var) into eax
movl    8(%ebp), %edx  ; and also into edx.
movl    (%edx), %edx   ; get the value from the address (dereference).
addl    $7, %edx       ; add 7 to it.
movl    %edx, (%eax)   ; and put it back into the same address.

Hence the address is passed, and used to get at the variable.

paxdiablo
A: 

The simple answer is that the object code generates a reference to the symbol where my_static_int is allocated (which is typically in the static data segment of your object module).

So the address of the variable is resolved at load time (when it is assigned a real physical address), and the loader fixes up the reference to the variable, filling it in with its address.

Loadmaster