0
void EventsStack::push(Event *e){
    EventNode *q = new EventNode();
    q->data = e;
    q->next = _top;
    _top = q;
}

void main() {
    EventsStack eventStack;
    Event e1(1);
    eventStack.push(&e1);
    Event e2(2);
    eventStack.push(&e2);
}

最初の質問: 私がするとき

eventStack.push(&e1);

e1 の ADDRESS をプッシュ関数に送信し、プッシュ関数はそれをポインターとして受信していますか? 私がやっているかのように:

Event *e = 1000 (1000 is the offset (address) of e1 for example on the stack)

?

2 番目の質問: main 関数を実行したときのスタックを説明するように求められました。ラインに着いたら

eventStack.push(&e1);

4 バイトの戻りアドレスと e1 への 4 バイトのポインターが関数のアクティブ化フレームとして割り当てられますか、またはこの状況では、eventStack はクラス EventsStack のオブジェクトであり、プッシュはそのメンバー関数の 1 つであるため、アクティブ化フレームはありませんか?

4

2 に答える 2

1

あなたの最初の質問に関して:式はポインタである&e1のアドレスを取ります。e1つまり、e1 has type Event&e1has type Event*、およびそれを逆参照するような値 (単項*演算子) は、 を使用した場合と同じ効果がありe1ます。これは、プッシュ関数に渡すものです。

また、スタックが必ずしも利用可能であるとは限らない他の場所からポインターを使用してオブジェクトにアクセスできる必要があるため、ポインターをスタック上の単なるオフセットにすることはできません。最新のデスクトップ マシンのほとんどは線形アドレッシングを使用します。つまり、ポインターは単なる整数ですが、常にそうであるとは限りません。一部の組み込みプロセッサではおそらくそうではありません (一部のメインフレームでは歴史的な理由から)。

2 番目の質問に関して: 正式には、関数がどのように呼び出されるかは完全に規定されていません。必要なのは、コンパイラが戻りアドレスと引数を、呼び出された関数がそれらを見つけることができる場所に置くことです。式eventStack.push( &e1 )では、関数は のアドレスeventStack( this関数内のポインターになります) と式 の2 つの引数を持ちます&e1。コンパイラがこれらを渡す方法は非常に異なり、ほとんどの場合、それらの型によって異なりますが、通常は、ほとんどの最新のマシンでは、最初の 3 ~ 5 個の引数は、適合する場合はマシン レジスタに入れられます (そして、渡すアドレスの両方が適合します)。そのため、マシン スタックにプッシュされるのは戻りアドレスだけです。また、パラメーターは通常、現在のフレームの一部とは見なされませんが、一部の古いプロセッサでは、コンパイラーはそれらをそのように扱いました。(あなたは「スタックを説明するように求められた」と言っています。質問は特定のマシン アーキテクチャに関するものですか、それとも何ですか?スタック上で実際に何が起こるかはコンパイラによって大きく異なり、Linux の g++ は Visual とはまったく異なることを行うことがよくあります。同じプロセッサ上で実行している場合でも、スタジオ.)

于 2013-02-05T18:54:55.553 に答える
0

最初の質問に関しては、はい:&オペレーターはイベントのメモリ アドレスを返します。

2 番目の質問については、複雑です。あなたが行った説明は、スタックがどのように機能するかについての根本的な混乱を示しているようです。このトピックに関するいくつかの入門資料に目を通すことを強くお勧めします。これにより、理解がはるかに深まります。

少しGoogleにアクセスすれば、今から数時間後に自分の質問に答えることができます:)。

于 2013-02-05T18:25:39.847 に答える