質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.13%

変数がメモリに格納される順番が変わらない

解決済

回答 7

投稿

  • 評価
  • クリップ 1
  • VIEW 372

Prometheus

score 9

前提・実現したいこと

変数宣言の順番によって、変数がメモリアドレスに格納される順番が変わることを確認するために、
int型変数のiと、char型変数のcを、それぞれ順番を変えて宣言したのですが、
メモリアドレスに格納される順番が変わっていませんでした。
理由を教えて頂きたいです。

発生している問題・エラーメッセージ

変数cを先に宣言した場合

ronin@ronin-ThinkPad-X280:~/Program$ gcc sample.c 
ronin@ronin-ThinkPad-X280:~/Program$ ./a.out 
変数iのアドレス 0x7ffe1c7df634
変数cのアドレス 0x7ffe1c7df633


変数iを先に宣言した場合

ronin@ronin-ThinkPad-X280:~/Program$ gcc sample.c 
ronin@ronin-ThinkPad-X280:~/Program$ ./a.out 
変数iのアドレス 0x7ffc0d5a2ee4
変数cのアドレス 0x7ffc0d5a2ee3

該当のソースコード

変数cを先に宣言

#include <stdio.h>

int main(){
  char c;
  int i;

  printf("変数iのアドレス %p\n", &i);
  printf("変数cのアドレス %p\n", &c);
}


変数iを先に宣言

#include <stdio.h>

int main(){
  int i;
  char c;

  printf("変数iのアドレス %p\n", &i);
  printf("変数cのアドレス %p\n", &c);
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • YT0014

    2020/06/27 13:44

    >変数宣言の順番によって、変数がメモリアドレスに格納される順番が変わる
    そもそも、変数がメモリに配置される保証すらないんですが。
    その情報のソースをご提示ください。

    多分、関数の外で宣言したら、順番通りになるとは思いますが、コンパイル環境によっては、それも崩れるかと。

    キャンセル

  • Prometheus

    2020/06/27 13:51

    『HACKING:美しき策謀』という本のp145~146を参考にしました。

    キャンセル

回答 7

checkベストアンサー

+6

宣言順とアドレスに関係はありません。どのように配置されるかはコンパイラに任されます。4 バイトのメモリが後に(スタックなので後ろから数える)確保されているのは、パフォーマンス上の理由による最適化の結果だと思います。詳しくは次を参照してください。

データ構造アライメント - Wikipedia

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/27 13:55

    回答ありがとうございます。
    変数の大きさによってアドレスが順序付けられるなど、かなり柔軟に対応してくれるのですね。

    キャンセル

  • 2020/06/27 13:59

    してくれるコンパイラ「も」あります。うろ覚えですが、Visual Studio と gcc はしてたと思います。色々なサイズの変数を定義して検証してみてください。

    キャンセル

+4

各変数が実メモリ上にどう配置されるかは言語仕様では規定していません。
つまりコンパイラの勝手.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/27 13:41

    ...かぶりまくりー^^;

    キャンセル

  • 2020/06/27 13:52

    ですね。 ;^^

    キャンセル

  • 2020/06/27 13:53

    回答ありがとうございます。
    変数の宣言順は関係ないのですね。

    キャンセル

+3

「変数がメモリアドレスに格納される順番」は、処理系・コンパイラ・リンカ、さらに最適化の有無等によって変わります。

なので、どういう順番でアドレッシングされるかも、決まった答えはありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/27 13:54

    回答ありがとうございます。
    変数の宣言順は関係ないのですね。

    キャンセル

  • 2020/06/27 15:56

    関係ないとは言えない、と推測されます。
    アライメントの変化しない、たとえば int a, b, c, d; と int d, c, b, a; なら宣言順に依存しそう。

    キャンセル

  • 2020/06/27 16:17

    そうですね「関係ない」ということではありません。関係はあって、変数の宣言順は影響したりしますが・・・。
    「アライメントの変化しない、たとえば int a, b, c, d; と int d, c, b, a; なら宣言順に依存しそう。」ではありますが、そういう限定的な宣言の話でなければ、結局、一般的に宣言順による「決まった答え」はありません。

    キャンセル

+2

「メモリアドレスにどのように配置されるか」
はコンパイラとコンパイル時の指定・実行系に依存すると思います。
構造体・配列であれば確認できるのではないでしょうか。
(メインフレームのCOBOLは、記述順にアロケートされましたが)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/27 13:52

    回答ありがとうございます。
    コンパイラの問題なのですね。

    キャンセル

  • 2020/06/27 13:54

    はい。ですが、確認してみよう という試みは面白いと思います。

    キャンセル

+2

オプティマイズやコンパイラの仕様などにもよりますが、想定される動作は、いかのようなものかと。

  int i; /* レジスタ変数に仮設定 */
  char c; /* レジスタ変数に仮設定 */

  printf("変数iのアドレス %p\n", &i); /* スタック変数に決定 */
  printf("変数cのアドレス %p\n", &c); /* スタック変数に決定 */


コンパイラが、スタック変数に決定した順番で決めていたら、ご提示のような結果になるでしょう。

余談
とあるCの一部のバージョンで、初期化文字列に文字数制限があったことがあります。
それを超える文字列を使いたいとき、このコンパイラのchar配列のメモリ配置が連続することを利用して、以下のようなコードを使っていました。

int hoge() {
    static char message[20] = "限界までの文字列です";
    static char dummy[] = "追加文字列。";
    message[20] = 0x20;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/27 13:53

    printf の順番によってアドレスが変わるということでしょうか?

    キャンセル

  • 2020/06/27 13:59

    そういう可能性もある、というだけで、未検証です。
    アライメントの可能性の方が高そうですが。

    キャンセル

  • 2020/06/27 14:01

    割り当ての前に構文木を作るものが多いんじゃないかと思うので、疑問でした。ありがとうございます。

    キャンセル

+1

コメントにしようかと思ったのですが、、、

他の人の回答どおりですが、参考として、、

例えば、データバスが 4バイトの時、 1byte(+3byte), 4byte, 1byteでは効率悪すぎです。どこまで効率良くは別ですが、大抵のコンパイラはやってるのではないとか思います。
その一方、この無駄で運よく動いてたコードもある. (char[1]なのに、4文字までOKとか...) バグなのですが、動いているコードで触れなかった。

また、メモリの確保は、明示的に宣言された変数だけでは無いので注意が必要。複雑な計算をする場合、コンパイラが途中計算用に、メモリを確保する事があり、その分、変数のアドレスが影響を受けます。
さらに、最適化などを行うと、逆に、変数はスタックに確保されず、レジスタだけとか、必要ないと、(内部的に)削除されます。こっちも注意。ただ、アドレスを取ると、必然的に確保されますが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

回答はされているのですが、質問の意図が、アドレス指定したいのであれば、
構造体を使うと可能かと思います。

しかし、目的は?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/30 14:29 編集

    CTFの勉強のために、スタックバッファオーバーフローによって、変数領域を上書きしようとしました。
    変数の宣言の順序によって、変数がメモリに格納される順番が変わるという趣旨の記述が、『HACKING:美しき策謀』に記載されていたため、自分の環境ではなぜ出来ないのか気になり、質問しました。

    キャンセル

  • 2020/06/30 14:54

    ひょっとしてローカル変数でなく引数ではありませんか?
    それなら宣言順にスタックに積まれますし、関数外部からインジェクションできます。

    キャンセル

  • 2020/07/01 08:55

    スタックバッファオーバーフローの実験なら、同じ形の変数であれば再現するかも。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る