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

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

ただいまの
回答率

89.06%

C アライメントに関して

受付中

回答 5

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 467

sample__

score 0

そもそもC言語のアライメントに関して本当に理解してやっている人はいるんですか?

理屈の話ではなく一般的にはx86CPUなら4バイト境界にアラインさせるのが一番効率がよいと言われています。
x86はメモリアクセスに寛容だから無理にアラインさせなくても一応アクセスは可能。
(逆に言うならばメモリの節約が可能)

メモリを節約しなければいけない状況
アクセス効率を重視する状況

などそれぞれの要件によってどのようにアライメントを揃えるかというのは変わってくると思います。

では、たまに見る

「2バイト整数は2の倍数のアドレスに配置・アラインさせる」

という記述は何ですか?

これは何を目的としたアラインのさせかたなんですか?

(まぁ、本当にアクセス効率を重視したいなら個々のアライメントというよりある程度の大きさのデータ配置を気にしたほうがいいのかな?)

リンク内容
イメージ説明
CPU とデータ型によって異なるが
⇒これはわかる。

⇒つまり1バイト整数のアラインメントは1バイト, 2バイト整数のアラインメントは2バイト, 4バイト整数/単精度浮動小数のアラインメントは4バイト, 8バイト倍精度浮動小数のアラインメントは8バイトである.

一般って何?

理解力が低い私にはとてもじゃないけど理解できない記事でした。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • ikadzuchi

    2020/07/29 23:44

    > 何バイト境界に~になる.
    > ここですね。
    一般はどこを指すかに対する返答でしょうか。
    一般に2の冪乗になることは疑問の余地はありませんね?
    あなたが疑問視しているのはnバイト整数のアラインメントがnバイトになるべきか否かですよね?
    どうも文章をきちんと読んでいるか疑問です。

    > そういえばキチンとしたソースというのはない。
    > 逆に僕はキチンとしたソース(日本語)を見つけられていません。
    何語でも構いませんが、質問の前提となっている物事がソース無しとなると、まずは前提を疑うのが先ではないかなあという気がしますね。
    1,2バイト整数を4バイトアラインで速くなる要因が私には思いつきません。

    キャンセル

  • sample__

    2020/07/31 23:52

    今回のx86において4バイトアライメントが一番効率が良いといったことを撤回します。

    アライメント関連の記事には4バイト境界にアラインさせるというのがよく書かれていますが
    私がそれを勝手にメモリアクセスの効率がよいものなんだと思い込んだだけのようです。

    ごめんなさい。

    キャンセル

  • FKD

    2020/08/03 14:21 編集

    蛇足かもしれませんが、x86系はPentiumあたりからデータバス幅が64bitだったりするので、現在はアライメントは8バイトが効率よいです。
    また、このあたりの話は、メインメモリとCPUキャッシュの速度差も考慮しないと腑に落ちないかもしれません。(メインメモリは遅いので、アクセス回数が最小になるようにアライメントをそろえる)
    以下を参照してみてください。(GIGAZINEの記事)
    https://gigazine.net/news/20180911-access-speed-history/

    キャンセル

回答 5

+4

C言語のアライメントに関して本当に理解してやっている人はいるんですか?

理解してる人はたくさんいると思いますよ。

理解力が低い私にはとてもじゃないけど理解できない記事でした

そう言われれば、プログラマが理解していなくてもそれほど困らない事かもしれませんね。なぜならアラインするのはCコンパイラですから。プログラマが知らない間にコンパイラは全ての変数を適切にアラインしてくれています。あなたがアラインメントを知らないばかりにプログラムが動かなかった、なんてことはなかったはずです。まずはご安心を。

でも時々、コンパイラがどうアラインするか、意識することがあります。それは構造体を使う時です。次のコードをコンパイルして動かしてみてください。

#include <stdio.h>
#include <stdint.h>
//#pragma pack(4)   // <= 試せるなら

struct A {
    double  d;      // 8
    float   f;      // 4
    int32_t a;      // 4
    int16_t b;      // 2
    int16_t c;      // 2
};
struct B {
    int32_t a;
    double  d;
    int16_t b;
    float   f;
    int16_t c;
};

int main(void)
{
    printf("A: %ld bytes.\n", sizeof(struct A));
    printf("B: %ld bytes.\n", sizeof(struct B));
    return 0;
}


struct A と struct B はどちらも同じメンバ変数を持っていますが、並べた順序が違います。私の手元で実行すると、結果はこうでした。

# ./a.exe
A: 24 bytes.
B: 32 bytes.


もしアラインメントが一切無いなら両方同じバイト数になりますが、そうはならない。メンバ変数の並びが違うので、それぞれのメンバをアラインした結果、 struct B には struct A よりも隙間が多くなったのです。
質問者もお手元で確かめてください。

私の場合、違いは8バイトです。構造体一個のサイズが8バイト違っても大勢に影響は無いでしょう。なにせ今時のパソコンはGBオーダーのメモリを積んでますから。
でも構造体を配列にしたら、その差は拡大します。例えば要素数1000の配列なら、違いは8000バイトです。それだけメモリが無駄になってしまいます。組込みの世界では今だってメモリサイズの制約が大きいので、こうしたことに敏感です。

構造体のメンバ変数は、プログラマが書いた通りに配置されます(Cコンパイラはメンバ変数の順序を変えない)ので、ここの順序はプログラマの責任です。気にするのは当然でしょう。

>「2バイト整数は2の倍数のアドレスに配置・アラインさせる」という記述は何ですか?

上のコードには int16_t 型のメンバ変数 b, c を含めました。b, c は2の倍数アドレスにアラインされるので二つ続けて並べれば、隙間なく配置できる=隙間を減らせるというわけです。

念のため繰り返しますが、アラインメントを理解できなくてもCプログラムを動かすことに大きな支障はないと思いますし、気にしなくて済む分野のソフトウェアはいくらでもあります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/31 23:53

    コンパイラの設計次第ですね。

    >困らない事かもしれませんね。
    仕事ではなく趣味としてやっている身としてはどうしても
    細かい部分も気になるものです。

    キャンセル

  • 2020/08/03 19:44

    気になる点、未解決な事があるんですよね?
    そこを明確にすれば誰かが答えると思いますが。

    キャンセル

+3

「2バイト整数は2の倍数のアドレスに配置・アラインさせる」 

メモリアクセスの効率を良くする(というよりは悪くしない)ではないですか?
16bitとか32bitのデータバス幅でアクセスしているなら、奇数アドレスに始まる16bitデータは物理メモリにアクセスが2回必要になる可能性があります。偶数アドレスで始まっていれば確実に1回でアクセスできます。

(余談)8088はこの仕様で"やっぱり8bitマイコン"だなぁ、と思わせたものでした。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/30 12:53

    >4バイトの倍数から始まるアドレスからデータが配置されていないなら少なからずアクセス効率は下がると思います。

    データバス幅32bitであれば、32bit単位でメモリから読み込むので、
    16bit要素が連続(配列等)していれば、一回で2要素読める可能性があります。(CPUキャッシュに乗ります)
    逆に、アクセス効率が下がるケースってなにかありますか?

    キャンセル

  • 2020/07/31 01:47

    > 「速度」を考えるならそもそもshortは選択肢になりません。
    あまりそうは思えなかったので試してみましたが、どうやら同じかshortがわずかに速いですね。
    コメント欄に長いコードを書くのは憚られるので言葉で説明すると、「「1000要素用意して順に加算」を100万回」をintとshortと1つ飛ばしのshortで、x64マシン上のgccで試しました。

    キャンセル

  • 2020/08/01 13:59

    8088が 8bit CPUの匂いがするするってのはまあ、時代背景でしょう。ソフトウェアより、ハードウェアの都合で、周辺機器(チップ)が 8bit CPUのものが流用できるので、安く上がるって事だったと思います。(で、16bitと威張れる)
    多分、時代を考えないと意味不明。

    キャンセル

+1

アライメントは、CPUのバス幅やアーキテクチャにより変わるもんです

#組み込み向けなどのメモリが制限されてる環境なんかでは、アライメント意識しないと、まともに動かすことはできませんな。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/29 22:02

    あ、wikiでもx86に関して
    "ただし、アライメントを整える必要がある場合がある"
    って書かれてたような・・・

    まぁ、そこまでアライメントに気をつかう場面があるかって言われたらないのかな(?)
    ちょっと前に知恵袋でも同じような質問した気がするが
    適格(?)に答えてくれた人はいなかったような・・・

    やっぱそこまで理解している人は少ないのかな
    (果たしてそれを理解している人がこのサイトを利用していて僕の質問を見てくれているかさえわからないが・・・)

    キャンセル

  • 2020/07/29 23:21

    最近流行りの殆どメモリ意識する必要ない言語しか触らない開発者だと、アライメントとか知らないって人は多いんじゃないですかね。(逆に言えば知る必要がないとも言う)
    そこまで意識したのは、数年前にアセンブラで画像処理用のライブラリ書いた時くらいかな…

    キャンセル

  • 2020/07/29 23:25

    やっぱそうなるんですかね。

    キャンセル

+1

maisumakun 2020/07/29 19:24
x86でも、SSEを扱う場合には「16バイト境界にアラインする必要がある」ような場面も出現します。

コメントで埋もれてしまうにはあまりにももったいないので、SSEじゃなくてAVX2ですが、その事例をteratailの回答で書いたことがあったので、紹介しておきます。

https://teratail.com/questions/140753#reply-213221

ソースコードは上記回答にあるリンク先のgistを見てください。

AVX2命令は256ビットを一度に扱うもので、アライメントのサイズは32バイトです。アライメント調整のために動的にメモリ確保しているところはaligned_allocを使っているのがわかると思います。

そもそもC言語のアライメントに関して本当に理解してやっている人はいるんですか?

理解していない人には、SSE等を扱うのは無理でしょう。ただ、CPUによって分岐を書く必要があったりするし、高パフォーマンスが必要になるライブラリ(例えばlibwebp等)以外は使っている人は少ないと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

まだ、閉じてないみたいなので、、

今、C言語とか、その他の高級言語でプログラムを書く時には、意識する必要のないものだと思います。VCだと、アライメントに合わせてメモリ割付けしてくれるし、特殊なパラメータ設定、または裏技でないと、不正な配置に置くことができないと考えています。

アライメントを考えるのは、少しでもメモリ効率を良くしようとか、少しでも速くなんて考える、または、組み込み系の非力なチップを使う時くらいではないでしょうか。そして、最近のPCで使われているチップ(Intel, ARM,...)では、キャッシュとか色々とあって、下手な(手作業の)最適化は、却って効率を落とすだけでしょう。

昔(20世紀)だと色々とありました。32bit CPUで、4byte整数を4byte境界に、合わせないとバスエラー例外とか、下位 2bitを無視してアクセスするCPUとか。byteアドレスと wordアドレスが違うものとか。(byte → word は、1bit シフト)

そういう意味では、(一般のアプリでは)アライメントを意識しなくても良い時代になったと思っています。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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