#実現したいこと
現在、古いソースコードを修正することになり、
ファイルヘッダー内変数のアライメント調整をすることになりました。
多少のファイル数、変数であればいいのですが、
ファイル&変数の数も膨大で、人力での作業はミスが発生しそうです。
自動でアライメントを調整する方法、もしくは、
現在のアライメント数を自動算出できる方法はないでしょうか?
#例:
アライメント 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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/04/26 11:22

回答4件
0
Visual Studio において構造体メンバーのアラインメント指定は、既にいくつか指摘がありましたが、プリプロセッサ命令での#pragma
か、コマンドライン指定で行うことができます。
以下は最新のVisual Studio 2019 での#pragma pack
のリファレンスです。
Microsoft Docs - Pragma Directives and the __Pragma Keywordpack pack
この内、#pragma pack のshow
や n
指定を組み合わせたものが、恐らくお望みの機能を提供できるものだと思います。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
総合スコア9369
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
総合スコア6385
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

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総合スコア6851
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
この場合は、char D; の後に3バイトのパディングバイトが入ります
で、そのアライメントをどうしたいんでしょうか
投稿2019/04/26 09:53
編集2019/04/26 09:54総合スコア88163
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/04/26 10:05
2019/04/26 10:48

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。