2016-08-14 3 views
-4

このコードが期待どおりに機能しないのはなぜかと思います。スタックは連続的に成長しますか?

typedef char uint8; 

    int main(int argc, const char * argv[]) { 
    // insert code here... 

    uint8 number_1 = 3; 
    uint8 number_2 = 1; 
    uint8 *PointerToNumber = &number_1; 

    printf("%d \n", *PointerToNumber); 
    ++PointerToNumber; 
    printf("%d \n", *PointerToNumber); 

    return 0; 
} 

このプログラムは3と-112を出力します。しかし、スタックが連続的に成長するならば3と1を出力してはいけませんか?

したがって、number_1を指していて、uint8型のポインタアドレスを増やすと、number_2の直後に宣言されていたので、number_2を指すべきではありませんか?

+7

これは、スタックの成長の問題ではなく、コンパイラがローカル変数をどのように配置するかという問題です。 –

+3

2つの変数の間に未使用のバイトが存在する可能性があります。変数が特定の場所や順序に配置されていること、またはまったく含まれていないことが保証されています(使用方法によって最適化できます)。 – Dmitri

+0

ローカル変数がどこにあるかに依存することはできませんが、 'number_2'はおそらく' number_1'の次の低い方のアドレスにあります。 –

答えて

3
++PointerToNumber; 
printf("%d \n", *PointerToNumber); 

は未定義の動作の原因です。あらゆる行動を正当化しようとするのは無意味です。プログラムの動作は、最適化レベル、さまざまなコンパイラー・オプション、および異なるコンパイラーの変更によって変更される可能性があります。

この場合、オプティマイザは、関数内で使用されていないため、number_2にスペースを割り当てないことを選択できます。

0

誰かがコメントしたように、number-2はおそらくnumber_1の次の低い方のアドレスにあります。 ++ PointerToNumberの代わりに、 - PointerToNumberは期待される結果を生成します( "1"を出力します)。

+0

再度、保​​証はありません。最適化を使用してコンパイルを試し、それがまだ動作するかどうかを確認してください。また、最適化をオフにすると、元のコードで期待していた結果が得られます。これは、コンパイラが変数と異なる方法で並べ替えたためです。最適化を使用するとどちらも機能しません。 – Dmitri

+0

ええ、私はそれを認識しています。スタックの全体的な概念をLIFOメモリとして検証したかっただけです。 – user148013

+0

ローカル変数の配置は、スタックがLIFOであることには関係ありません。関数が呼び出されたときに通常発生することは、呼び出し元がパラメータと戻りアドレスをスタックにプッシュして関数を呼び出すことです。呼び出された関数は、フレームポインタをスタックポインタの値に設定します。スタックポインタは、関数がローカルストレージに必要なスペース分だけ減分されます。局所変数には、その空間内の位置が割り当てられます(フレームポインタからの負のオフセットとして表されます)。しかし、そこにはどこにでも置くことができます。それは完全にコンパイラに任されています。 –

関連する問題