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

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

ただいまの
回答率

90.77%

  • C

    3462questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • GCC

    134questions

    GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

アラインメントのサイズ

受付中

回答 3

投稿

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

strike1217

score 550

構造体のアラインメントについては過去に質問したので、今回は別の話です。

リンク内容

4バイト整数または4バイト浮動小数をメモリに格納する場合, 先頭アドレスが4の倍数になるようにすれば上図の1ワードに収まるため, 1回のメモリアクセスで読み書きできる. このようにデータの先頭アドレスを4の倍数にすることを, 「4バイト境界にアライン (align:整列,位置合わせ) する」という.

64bitシステムだと8Bなので、8の倍数にすれば美しくなるんですかね。

char buf[a];  // aが8の倍数


ところがアセンブリ言語を見ると64bitでもスタックは32bitです。
つまり64bitでもアラインメントは4の倍数にしなくてはダメという事ですよね?
このサイトの説明が変なのでしょうか?
8B? 4B?

私の本の中にこう書いてあります。

malloc() calloc() realloc()により割り当てたメモリについては、C言語すべての標準の型を正しくアラインメントするようにPOSIXでも定義されています。Linuxでも上記ライブラリ関数は、32bitシステムは8バイト境界に、64bitシステムでは16バイトにアラインメントします。

ヒープ領域はスタックとは別物なのでアラインメントも異なるという事ですかね。
各領域ごとにアライメントが決められているんでしょうか??

1回のメモリアクセスで読み書きできる. このようにデータの先頭アドレスを4の倍数にすること

この説明では全く分かりません。
CPUによって固定ならどんな領域でも64bitなら8Bにしなくてはならないはずです。

さらに謎な点が・・・
アライメントはそのシステムのアーキテクチャによって固定ですよね?

#define _XOPEN_SOURCE 600
#define GNU_SOURCE

#include<stdlib.h>

int posix_memalign(void **memptr, size_t alignment, size_t size);


任意のサイズでアラインメントを可能にする関数ですが、任意のアライメントってどういうことですか??

Linux 64bit x86_64です。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+2

アライメントはそのシステムのアーキテクチャによって固定ですよね?

いえ、状況によってアラインメントは異なります

マシン内では、整数のアライメントはふつう、整数自体の長さ以下となります(そうでないと、整数配列に隙間が空いて、効率が悪くなります)。32ビット整数なら4バイト境界、64ビット整数なら8ビット境界、SSEで使うような128ビット整数は16バイト境界というようになることもあります。もちろん、1バイトのchar好きな場所に置けます

malloc()のアライメントは、大きな型の変数を入れても問題ないように、大きなアライメントを取るようになっています…が、SSEなどアセンブラで特殊な型を触る場合にはそれでも合わないので、手動調整が必要になる場合もあります。

「アライメントを手動で調整する機能」は、基本的に「バイナリデータが特定のアライメントで決め打ちになっているような場合」に使うもので、処理中にずらすようなことはあまり行いません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/25 14:28 編集

    前から思っていたんですが、変数の型のサイズとアラインメントって何が違うんですか?
    偶然同じなんですか?

    int : 4B
    char 1B

    キャンセル

  • 2017/09/25 14:34 編集

    x86の浮動小数点計算は、(x64でSSEに移行するまで)80ビット精度があったので、それをそのまま扱う「long double」を使える環境もありました。

    ただ、「10バイトアライン」では処理の手間なので、4バイトや8バイトで切り上げてアラインすることになります(sizeofもアライメントに合わせる隙間を入れて、12バイトや16バイトとなります)。

    キャンセル

  • 2017/09/25 14:47

    アライメントは変数によっても異なり、領域によっても異なるという事ですかね??

    キャンセル

  • 2017/09/25 14:53 編集

    mallocの場合の扱いは、「領域の違い」というより「何が入るかわからないから、大きめに取っている」という話です(16バイト境界に揃えておけば、8バイト・4バイトなどのアラインとして使っても全く問題ないので、「大は小を兼ねる」ということです)。

    キャンセル

  • 2017/09/25 14:59

    あ、なるほど!ヒープの場合はそういう考え方なんですね!

    キャンセル

+2

質問文から察するに、「アラインメント要件」と「(実際の)アラインメント」を混同されているようです。

  • アラインメント要件:CPUアーキテクチャにおいて、型(type)毎に 最低限満たすべき アラインメントが決められています。例:char型では1int型では4double型では8など。
  • (実際の)アラインメント:プログラム実行時に決まる、変数や動的確保メモリのアドレス値。例:malloc()関数が確保するメモリ領域のアライメントは8など。

(実際の)アライメントは、アライメント要件を満たす必要があります。mallocが返したアドレス値のアラインメントが8であれば、それより 小さいアライメント要件を持つ 型(type)を安全に格納できます。maisumakunさん回答にある「大は小を兼ねる」のイメージが分かりやすいかと思います。


各領域ごとにアライメントが決められているんでしょうか??

(実際の)アライメントは、コンパイル(静的リンク)およびプログラムロード(動的リンク)に決定されます。つまり、プログラムがメモリ上にロードされるときまでに最終決定されるものです。

アライメントはそのシステムのアーキテクチャによって固定ですよね?

「アライメント要件」はアーキテクチャで決まります。

任意のアライメントってどういうことですか?

前述の説明通りです。C言語の仕様により、「動的確保されるメモリアドレスには、任意の型を配置できること」が保証されています。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/26 20:54

    スタック領域が4Bであることは、アライメント要件の方ですか?

    キャンセル

  • 2017/09/26 22:20 編集

    狭義のアライメント要件は 型(type) に対する要件のみを指すことが多いです。それ以外には、ABI(Application Binary Interface) により追加でアライメント要件を要請されることがあります。スタックについては https://qiita.com/yohhoy/items/54633faf0546f8cd0e3a をどうぞ。

    キャンセル

  • 2017/09/26 22:36

    むむ・・・難しい・・・

    「アラインメント要件」と「(実際の)アラインメント」は別物ですよね。
    実際のメモリのレイアウトはアラインメント要件とは必ずしもピッタリと一致していないという事でしょうか?

    実際のアラインメントは動的確保の場合は実行時に決まりますが、スタックの場合はアセンブル段階で決まるんですか?リンカ段階ですか?

    キャンセル

  • 2017/09/26 22:45 編集

    > 実際のメモリのレイアウトはアラインメント要件とは必ずしもピッタリと一致していないという事でしょうか?
    はい。maisumakunさんコメントや本回答をもう一度ご確認ください。例えば、int型のアライメント要件が4の場合、実際のアライメントは4または8または16または32...であればOKです。

    > スタックの場合はアセンブル段階で決まるんですか?リンカ段階ですか?
    いずれでもなく、実行時です。例えば https://teratail.com/questions/25921 の質問文中では、「and esp,0xfffffff0」のように実行時にスタックポインタ・レジスタ(esp)の値を調整しています。

    キャンセル

  • 2017/09/26 22:56

    >「and esp,0xfffffff0」のように実行時にスタックポインタ・レジスタ(esp)の値を調整しています。
    objdumpなどしたアセンブリを見れば実際のアライメントが分かるんですね!

    「CPUが64bitなら8バイト境界」とはどういう事でしょうか?
    これは実際のアライメントの方の話ですかね?

    キャンセル

  • 2017/09/26 23:01

    > 「CPUが64bitなら8バイト境界」とはどういう事でしょうか?
    ??? どこから出てきた話ですか?

    キャンセル

  • 2017/09/26 23:06 編集

    あら・・・CPUが64bitであることとアライメントはなんの関係もないんですか?

    https://teratail.com/questions/37555
    「32bit CPUなら4バイト境界、64bit CPUなら8バイト境界が多いです。 」

    http://www5d.biglobe.ne.jp/~noocyte/Programming/Alignment.html
    「アラインメントは何か?」のところです。

    キャンセル

  • 2017/09/26 23:41

    > http://www5d.biglobe.ne.jp/~noocyte/Programming/Alignment.html
    > 「アラインメントは何か?」のところです。
    そこには「現実には,Nビット CPU のデータバス幅がNビットであるとは限らない.x86 を例に取ると,32ビット CPU とは言いながら Pentium 以降は64ビット・データバスである.」と書かれていますし、
    さらに「誤解1:(32ビット CPU では) 構造体は常に4バイト境界に配置される.」というセクションまで作って説明がされていますよ。
    たぶんあなたは誤解1をやった人(の1人)です。

    キャンセル

  • 2017/09/26 23:45

    むむ・・・

    「現実には,Nビット CPU のデータバス幅がNビットであるとは限らない.」
    そうですね。
    では、CPUのbit数はアライメントとは何の関係もない・・・ということで良いんですかね?

    キャンセル

  • 2017/09/27 00:27

    > https://teratail.com/questions/37555
    > 「32bit CPUなら4バイト境界、64bit CPUなら8バイト境界が多いです。 」
    こっちの方の発言も、文脈から「double型のアラインメント」の話であって、アラインメント全般の話じゃないですね。(その前にshort型のアラインメントが2という話も出てきますし。)

    それに、「境界をどこに調整するかは処理系(主にCPUの都合)によって異なり、32bit CPUなら4バイト境界、64bit CPUなら8バイト境界が『多い』です。」 と言っているのであって、CPUが64bitなら『必ず』8バイト境界なんて言ってないですよ。

    キャンセル

  • 2017/09/27 00:42

    ふむー。だんだんわかってきました。

    キャンセル

  • 2017/09/28 13:15

    アライメントがずれてても遅い(一つのデータを取得するのにデータバスを2回使う)だけで動くには動く、ってCPUもありますね。

    キャンセル

+1

「アライメントとは?」については皆さんの回答と議論がすでにあるので、
posix_memalign()についてだけ。

posix_memalign() は通常用途ではなく、ハードに依存してて例えば1024バイトきざみのアドレスでないとうまく動作しない、あるいはその方が速くなる、というような条件がある場合に利用します。

通常のアプリケーションでも本来は意識しなければならないデータバスの問題とかであれば、コンパイラとライブラリがアーキテクチャ(x64など)を理解しているのでmalloc()で良いです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/30 00:03

    う~~~ん。
    大きなアライメントが必要になる場面がいまいちよくわからないんですよね。

    キャンセル

  • 2017/10/02 14:53

    ぱっと思いつくのは、sysconf()やmlock()あたりと組み合わせて、ページ境界に合わせてメモリ確保&ページロックしちゃうようなコードを書きたいときとか。

    キャンセル

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

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

関連した質問

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

  • C

    3462questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • GCC

    134questions

    GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。