2

だから私はこのコードを持っているとしましょう

int my_static_int = 4;
func(&my_static_int);

明らかに、関数にmy_static_intへのポインターを渡しました。しかし、コードがコンパイルされるとどうなりますか?私が検討したアベニュー:

1)非ポインター変数を宣言すると、Cは自動的にそのポインターを作成し、typedefs my_static_intのような内部的な処理を*(internal_reference)にします。

とにかく、私の質問が十分に説明的であることを願っています

4

5 に答える 5

4

ポインタは、人間が何が起こっているのかを理解するのに役立つ単なる用語です。

&演算子を変数とともに使用すると、単にのアドレスを意味します。実行時に「ポインタ」は作成されません。変数のアドレスを関数に渡すだけです。

あなたが持っている場合:

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

この場合、pはメモリアドレスを保持する変数です。そのメモリアドレスの中にはintがあります。

于 2010-10-06T00:30:32.590 に答える
2

コードが内部でどのように見えるかを本当に知りたい場合は、コンパイラにアセンブラコードを生成させる必要があります(オプション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.

したがって、アドレスが渡され、変数を取得するために使用されます。

于 2010-10-06T00:46:22.340 に答える
1

コードがコンパイルされると、関数は変数funcのアドレスをパラメーターとして受け取ります。my_static_int他には何もありません。

非ポインター変数を宣言するときに、暗黙のポインターを作成する必要はありません。どうやってこの奇妙な考えにたどり着いたのか、あなたの質問からは明らかではありません。

于 2010-10-06T00:33:43.613 に答える
0

アセンブリの出力を見てみませんか?これは、オプションをgcc使用する-Sか、(システムがGNUツールチェーンを使用している場合)objdump -d結果のオブジェクトファイルまたは実行可能ファイルのコマンドを使用して行うことができます。

于 2010-10-06T00:32:07.367 に答える
0

簡単な答えは、オブジェクトコードmy_static_intが割り当てられたシンボルへの参照を生成することです(これは通常、オブジェクトモジュールの静的データセグメントにあります)。

したがって、変数のアドレスはロード時に(実際の物理アドレスが割り当てられたときに)解決され、ローダーは変数への参照を修正して、そのアドレスを入力します。

于 2010-10-06T01:38:22.607 に答える