コードが内部でどのように見えるかを本当に知りたい場合は、コンパイラにアセンブラコードを生成させる必要があります(オプションgcc
を使用してこれを行うことができ-S
ます)。
Cとポインターを最も深いレベルで実際に取得すると、変数の値ではなく、渡される変数のアドレスにすぎないことがわかります。ポインタはコードからスタックに直接移動されるため、ポインタを保持するために追加のメモリを作成する必要はありません(アドレスは、実行時ではなく、リンク時またはロード時に設定されている可能性があります)。
コンパイルされたコードはすでに型とその操作方法を知っているので、内部型を作成する必要もありません。
これは実装固有であることを念頭に置いて、次のコードを検討してください。
int my_static_int = 4;
static void func (int *x) {
*x = *x + 7;
}
int main (void) {
func(&my_static_int);
return 0;
}
これをコンパイルしgcc -S
てアセンブラを取得すると、次のようになります。
.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
重要な点は次のセクションです。
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.
したがって、アドレスが渡され、変数を取得するために使用されます。