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

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

新規登録して質問してみよう
ただいま回答率
85.31%
C

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

Q&A

4回答

3558閲覧

ヘッダー内変数のアライメント調整方法について

dodo-taka

総合スコア14

C

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

0グッド

0クリップ

投稿2019/04/26 09:22

編集2019/04/26 09:53

#実現したいこと
現在、古いソースコードを修正することになり、
ファイルヘッダー内変数のアライメント調整をすることになりました。

多少のファイル数、変数であればいいのですが、
ファイル&変数の数も膨大で、人力での作業はミスが発生しそうです。

自動でアライメントを調整する方法、もしくは、
現在のアライメント数を自動算出できる方法はないでしょうか?

#例:
アライメント 8byte
○○○.h内
{
//省略
int A; // 4byte
int B; // 4byte
int C; // 4byte
char D;// 1byte
//省略
}

↑の場合、合計13byteだが、アライメント8byteであるため、
3byte分足りていない。

#開発環境
Windows7 Pro 64bit
VC++2005 SP1
Microsoft Visual Studio 2005
Version 8.0.50727.867 (vsvista.050727-8600)
Microsoft .NET Framework
Version 2.0.50727 SP2

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2019/04/26 09:43

構造体メンバーのアライメントを指定する方法は多くの処理系で用意されていますが、処理系ごとに細かい指定方法が変わりますので、お使いの処理系(Cコンパイラ)を明示された方が正確な回答が得られやすくなります。
dodo-taka

2019/04/26 09:55

レスありがとうございます。 開発環境情報を追記しました。
maisumakun

2019/04/26 11:22

実際に動かす環境は同じWindows x64、ということで間違いないでしょうか。
guest

回答4

0

Visual Studio において構造体メンバーのアラインメント指定は、既にいくつか指摘がありましたが、プリプロセッサ命令での#pragmaか、コマンドライン指定で行うことができます。

以下は最新のVisual Studio 2019 での#pragma packのリファレンスです。
Microsoft Docs - Pragma Directives and the __Pragma Keywordpack pack

この内、#pragma pack のshown指定を組み合わせたものが、恐らくお望みの機能を提供できるものだと思います。showは、現在の構造体アラインメントの値をコンパイル前のプリプロセス時に出力ウィンドウに出力することができます。人間による視認での確認ですが、参考にはなると思います。

例えば以下のコードですが、

C

1#include <stdio.h> 2 3/* 8バイトアラインメント */ 4#pragma pack(8) 5#pragma pack(show) 6 7struct abc_pack8 { 8 int A; 9 int B; 10 int C; 11 char D; 12}; 13 14/* 1バイトアラインメント */ 15#pragma pack(1) 16#pragma pack(show) 17 18struct abc_pack1 { 19 int A; 20 int B; 21 int C; 22 char D; 23}; 24 25int main(int argc, char *argv[]) 26{ 27 printf("sizeof(struct abc_pack8)=%d\n", sizeof(struct abc_pack8)); 28 printf("sizeof(struct abc_pack1)=%d\n", sizeof(struct abc_pack1)); 29 return 0; 30} 31 32/* 33実行時のコンソールへの出力結果: 34sizeof(struct abc_pack8)=16 35sizeof(struct abc_pack1)=13 36*/

これをビルドすると以下のような内容が出力され、構造体アラインメントの値を確認できます。

CMD

1------ すべてのリビルド開始: プロジェクト: ConApp1, 構成: Debug Win32 ------ 2プロジェクト 'ConApp1'、構成 'Debug|Win32' の中間出力ファイルを削除しています。 3コンパイルしています... 4ConApp1.c 5c:\project\conapp1\conapp1.c(6) : warning C4810: pragma の値 pack(show) == 8 6c:\project\conapp1\conapp1.c(17) : warning C4810: pragma の値 pack(show) == 1 7...

尚、確認した限りでは、Visual Studio 2008までは同じ指定が使えました。質問者さんが使用予定のVisual Studio 2005 では違うかもしれないのでその点は気を付けてください。

目で見ての確認が心もと無いのであれば、assertなどを組み合わせ、実行時に意図していないサイズを検出したらプログラム自体をブチ落とすという手も一案です。

C

1#include <assert.h> 2/* 実行時に検出(DEBUG時のみ) */ 3assert(sizeof(struct abc_pack8) == 16); 4assert(sizeof(struct abc_pack1) == 13); 5

これは私が、質問者さんと同じような状況、つまりポーティングのような作業で固定長のサイズのデータを正しく、プログラマーの意図通りに取り扱えているか、以前のものと変わっていないか、などを検出するときによく使う手です。offsetofのようなマクロを併用して、構造体メンバーのオフセット位置が正しくなっているかなどにも使います。

コマンドラインオプションでの指定なども組み合わせて、適切な使用方法を検討してみると良いと思います。
Microsoft Docs - /Zp (構造体メンバーの配置)

投稿2019/04/26 14:50

dodox86

総合スコア9369

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodo-taka

2019/05/06 00:50

連休で返信できず、申し訳ありません。 情報ありがとうございます。 一度、試してみます。
guest

0

古いコードってことですが、元はなんでコンパイルしていたのでしょうか?

その時と同じ設定が必要になるのではないかと思います。
多分、、、ですが、コンパイルエラーにならないバグがあって、アライメントで未割当てとなっていた場所にアクセスしていたとか。

C

1 char a[1]; 2 char b[100]; 3 .... 4 n = 50; 5 .... 6 a[n] = 10;

なんてコードが昔、動いてました。 ?? と思って調べたら、 b[] が使われていなかった。 (今だと検出される?)
そんな可能性も調べる必要がありそうですね。unionなんてのも無いでしょうか?

アライメントの指定については、他の方の書かれている通りですね。

投稿2019/04/26 14:50

pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodo-taka

2019/05/06 00:50

>古いコードってことですが、元はなんでコンパイルしていたのでしょうか? 元々は、x86で動いていたコードなのですが、 どうしてもx64環境に移植する必要がありました。 また、元コードがアライメントを意識されておらず、修正必須の状況です。
guest

0

参考:
構造体パッキング
前へならえ
//

c

1struct abc { 2 int A; 3 int B; 4 int C; 5 char D; 6}; 7// 8int main(void) 9{ 10 struct abc val; 11 12 return 0; 13} 14

上記コードで、以下のワーニングがでます。VCはわからないのですがエラーの設定で最強のエラーチェックにすれば出るのではないかと?

text

1usr ~/Project/test % clang -Weverything st.c 2st.c:10:16: warning: unused variable 'val' [-Wunused-variable] 3 struct abc val; 4 ^ 5st.c:1:8: warning: padding size of 'struct abc' with 3 bytes to alignment boundary [-Wpadded] 6struct abc { 7 ^ 82 warnings generated. 9usr ~/Project/test % 10

投稿2019/04/26 09:58

編集2019/04/26 10:35
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodo-taka

2019/04/26 10:48

VC++の警告レベルを3→4に変更した所、 飛んでもない量のWarningが出ました・・・ コードを1から記述するのなら良いのですが、 過去コードの修正なため、対応は難しそうです・・・ ただ、情報としては参考になりました。ありがとうございます。
dodox86

2019/04/26 13:45 編集

構造体メンバーのアラインメントに関する限り、Visual Studo 2017 では同じコードで警告は出ませんでしたね。警告レベル最高 "/W4", 構造体メンバーアラインメイント8バイト強要"/Zp8"
guest

0

この場合は、char D; の後に3バイトのパディングバイトが入ります

で、そのアライメントをどうしたいんでしょうか

投稿2019/04/26 09:53

編集2019/04/26 09:54
y_waiwai

総合スコア88163

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodo-taka

2019/04/26 09:57

はい。3byteが入ることになるのですが、 この3byteが足りないことを自動的に調査できないかなと思っています。 今回の例は、数行しかないため、間違う可能性は少ないと思うのですが、 ファイル数&変数の数も膨大なため、 自動で調べる方法はないか、質問に至った次第です。
y_waiwai

2019/04/26 09:59

足りないことを調査するとは? ちとやりたいことが見えないので、そこら辺の詳しい説明を質問を編集して追記してくだされ
cateye

2019/04/26 10:05

VCってパデングが入るってワーニングで出ないですか?
dodo-taka

2019/04/26 10:17

>y_waiwaiさん 当方の環境では、アライメントを8byteで揃えない場合、 プログラムの挙動がおかしくなる場合がありました。 そのため、3byte分を char dummy[3];と明示的に宣言する必要があったためです。 >cateyeさん 私の環境では、発生しませんでした・・・
cateye

2019/04/26 10:48

〉プログラムの挙動がおかしくなる・・・今時のコンパイラで? 開発環境と実行環境が違いますか?
y_waiwai

2019/04/26 11:33

何バイトのアライメントかってのは、コンパイラにより決まりますんで、同じコンパイラでコンパイルする限りは同じアライメントです。 #そりゃpragmaやらattributeで設定してるものはそれに従いますが
y_waiwai

2019/04/26 11:49

ということで、アライメントはコンパイラに依存するので、コードの位置によって変わるもんじゃないです コードを調査するのは無駄でしかないですぜ
dodo-taka

2019/05/06 00:46

>cateyeさん 開発、実行環境ともWindows7 Pro 64bitで、x64でビルドしています。 >y_waiwaiさん アライメントを8byteで揃えないと、とある変数の挙動が意図しないものになってしまい、 UINT dummy;などダミーの変数を追記して、現状アライメントを揃えています。 ですので、現状ですと、コードというかヘッダーファイル中心にチェックしているのが現状です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問