アプリ版:「スタンプのみでお礼する」機能のリリースについて

 プログラム解析のため10個ぐらいのC言語ファイルで
出来たソフトをビルドしたのですが、次の警告が最初の
ファイル以外に対して、それぞれ出ます。

>C1300 (W) Command parameter specified twice
> 同じコンパイラオプションを2度以上指定しています。
>同じコンパイラオプションの中で最後に指定したものを
>有効とします。

 define 等が2度以上書かれているのかなと思い、あるファイル
の中身を全て削除しました。中身が空なだけでファイルは消して
いません。
 それなのに、そのファイルに対して上の警告が出ます。

 この警告は何でしょう。何も書いて無いのにこのような警告が
出るのでしょうか。

 宜しくお願いします。

A 回答 (12件中1~10件)

>  int など偶数バイト単位で構成されるデータは、偶数番地にしか配置


> 出来ません。CPUの依存性が有ります。

H8/300HやH8Sは16ビットの境界調整を要求します。
そのため、例えば

struct A
{
 char a;
 int b;
};

という構造体では、aとbの間に1バイトのパディングが入ります。そして、結果として、struct A型のオブジェクトは必ず偶数番地に配置されます。
ところが、質問者さんは、

> 「構造体の境界線が奇数アドレスになる」

という警告が出たとおっしゃいました。
ということは、#pragma pack指令等を用いて、先ほどのstruct A構造体を3バイトにするような操作を明示的に行っている以外には考えられません。

このようなことをするのは、例えば、何らかの通信プロトコルでそのような並びが要求されているとか、ヘテロなマルチプロセッサ環境における共有メモリに書き込むためとか、特殊な事情があるのではないかといっているのです。
なお、#pragma pack指令等でパディングをなくした場合、ハードウェアの仕様がどうであれ、奇数番地に配置されたint型オブジェクトを、ソフト的に分割してアクセスすることになります。

>  コンパイラに行わせるのでは無く、プログラマがダミーを
> 入れて認識しておくべきだろうと言っているのです。

ダミー部分を含めて、通信相手や格納先と合意が取れている必要があるのでない限り、そのようなダミーは入れるべきではありません。
先ほど紹介していただいた、

http://www.g-ishihara.com/c_st_01.htm

では、ダミーを入れる根拠として移植性を挙げていました。
しかし、移植性の話をするのであれば、int型やlong型などのバイト数を特定の値に仮定するのは間違っています。
より具体的にいえば、同じH8/300Hでも、HEWであればint型は16ビットでも、GCCであればコンパイラオプションによって16ビットと32ビットを選択可能です。GCCのlong long型にいたっては、バージョン3.3.xまでは32ビットですが、3.4.x以降は64ビットです。GCCのdouble型は32ビットですが、それでは標準規格を満たせないこともあり、μCLinux用のパッチを適用したGCCなどでは64ビットになります。

このように、CPUは同じでもコンパイラの種類やバージョン、あるいはコンパイラオプションが変わっただけで型のサイズはかなり変わるのです。
それを無視してダミーを入れると、移植性を損なって将来に不安を残すだけですし、下手をすると今回も動かなくなります。
    • good
    • 0
この回答へのお礼

 こんにちは

> 「構造体の境界線が奇数アドレスになる」
という警告が出たとおっしゃいました。

 「構造体の境界線が奇数アドレスになるから、パディングして
偶数に揃えた。」
 と言う事を言いたかったのです。すなわち次の警告の内容です。 

「構造体のメンバ間に境界調整の空き領域を生成しました。」

 言葉足らずだったこも知れませんが、此処に投稿してくれる
方には分かってくれると思っていたのですが。

 以前にHC3048のアセンブラで、データを変更したため奇数バイト
になったら、その後に書かれている命令が暴走しました。
 マシン語が奇数番地から始まっていたからです。アセンブラも警告してくれないし、CPUも「ジャンプ先アドレスが奇数になっている」
と言うような事を知らせてくれる割り込みが用意されている訳でも
有りません。
 プログラマが注意して境界管理をしなくてはいけません。

16ビット単位のデータの読み書きに対しては確認していま
せんが、奇数アドレスですと同じようなエラーになるでしょう。
 そんな訳で、コンパイラが境界管理をする前に自分で
パディングして境界調整をするべきだと書いたのです。

 色々と回答して下さるのは嬉しいのですが、脇道に深く入り
過ぎました。
 当初の質問も皆様の温かい回答により、解決しました。
 皆様、有り難う御座いました。

 このパディングの話は、この辺で終わりにしませんか。

お礼日時:2008/10/08 00:58

横槍かつ横道ですが。


>「C0016 (I) Padding in structure
>構造体のメンバ間に境界調整の空き領域を生成しました。」
は初出ですよね? 残念ながらそれ以前の文章からは
>コンパイラに行わせるのでは無く、プログラマがダミーを
>入れて認識しておくべきだろうと言っているのです。
は読み取れないのですが。

ここまでの文章では「何らかのオプションにより意図的に境界からずらしてコンパイルし、実際にずれた状態は修正されずコンパイルが行われている。」と読めます。そして、実際にずれた状態でコンパイルされていて、それで正常に動くのであれば、それを修正するのは危険です。
今回は単に「コンパイラが警告を出した上で調整」していたのを、「自分で調整」するようにしただけなので、正当な修正です。

ただ、PCの処理系の場合は普通は黙って境界調整します。通常警告が出る条件やメッセージは処理系に依存します。ですので、警告について正しい理解をするには、警告のメッセージそのものを見るしかありません。

ちなみに、バスエラーがでるかどうかは処理系依存でして。たとえばWindowsのVisual Cで試すと、
char arr[10];
int *p;
p = (int*)(arr + 1);
*p = 10;
printf("%d", *p);
これが動くんですね。
    • good
    • 0
この回答へのお礼

 有り難う御座います。

 No.12でご返事とお礼に変えさせて頂きます。

お礼日時:2008/10/08 01:03

>  私の考えは、次のURLの最後に書いてある


> 「構造体を設計するときは、このようにアライメントを考えた構造にするようにしましょう。」と言う事です。

そのサイトに書いている内容は、各データ型のサイズを仮定している時点で移植性がありません。
間違った情報を鵜呑みにするのはやめましょう。

そして、今回の場合は、意図的に構造体が奇数番地から始まる可能性があるような設定をしているわけですから、原則論ではなく、特殊な事情があると考えるのが妥当です。
    • good
    • 0
この回答へのお礼

 jacta さんは勘違いしていませんか。

 int など偶数バイト単位で構成されるデータは、偶数番地にしか配置
出来ません。CPUの依存性が有ります。
 パソコンのCPUだったら、32ビット単位だと思います。

 それでコンパイラは次の警告を出し、1バイトの空き領域
を作り、偶数番地に配置するのです。

「C0016 (I) Padding in structure
構造体のメンバ間に境界調整の空き領域を生成しました。」

 コンパイラに行わせるのでは無く、プログラマがダミーを
入れて認識しておくべきだろうと言っているのです。

お礼日時:2008/10/07 01:04

HEWの中でCコンパイラを起動しているのですよね?


バージョンによって異なるかもしれませんが、http://monoist.atmarkit.co.jp/fembedded/h8/h8pri …の図2の右下にあるのが「コンパイラオプション」です。
質問者の使っている環境では、その部分の表示はどうなっていますか?
警告メッセージから判断すると、重複指定されたコンパイラオプションがあるのではないかと想像できます。
個々のコンパイラオプションの意味は、コンパイラのマニュアルを参照して確認してください。
    • good
    • 0
この回答へのお礼

 salsberry さん、及びNo4の 0x131cc6e さん、
有り難う御座います。

 解決の糸口が分かりました。調べてみると、
-lang=c -nologo -sj -lan=c
 と書いてあります。-lang=c と -lan=c が同じ意味で
ダブっているのではと思い、-lan=c を削除したら
警告が消えました。
 他にも「ケース文をIF文にした」と言うような警告が
出るのですが、「-case=table」にヒントが有りそうです。

 どんなオプションが有るのか、それを解説してあるマニュアルが
有るか探してみます。

 どうも有り難う御座いました。

お礼日時:2008/10/07 00:40

> この警告が出るのは、CPUの事情を知らないプログラマのミスです。



断定はできませんが、おそらく違います。

Cコンパイラは、ハードウェアの仕様で16ビット以上の変数が偶数バイト境界に整列していなければならない場合、デフォルトでは勝手にそのように配置します。奇数バイトに配置するには、コンパイラオプションや#pragma指令などを使って、明示的に指定しなければなりません。

明示的に奇数バイトに配置しているということは、何らかの事情でそうすることが必要だということです。
ちなみに、#pragma packなどでint型を奇数バイトに配置した場合、コンパイラは上位バイトと下位バイトを分割して読み書きするコードを生成するなどの方法で対応することになるはずです。
    • good
    • 0
この回答へのお礼

 回答有り難う御座います。
 
 私の考えは、次のURLの最後に書いてある
「構造体を設計するときは、このようにアライメントを考えた構造にするようにしましょう。」と言う事です。

http://www.g-ishihara.com/c_st_01.htm

お礼日時:2008/10/06 20:50

HEWは頻繁バージョンアップします。


前のバージョンならエラーが出なくても新しいバージョンで仕様が変わる事もあります。
プログラムの内容が理解できないまま修正するのは危険です(動いているように見えてもある日突然止まるかもしれません)
可能であれば、開発環境をまるごと(ハードディスクのコピーとか)入手することをお勧めします。
    • good
    • 0
この回答へのお礼

 回答有り難う御座います。

>プログラムの内容が理解できないまま修正するのは危険です

 理解するためにいじっているのです。まずは警告が出ないように
まともなソフトに訂正したい。

 警告の理由を調べているのです。

>可能であれば、開発環境をまるごと(ハードディスクのコピーとか)入手することをお勧めします。

 外の会社で誰が作ったか分からないソフトを改造するのですから
無理ですね。

お礼日時:2008/10/06 01:10

> 「構造体の境界線が奇数アドレスになる」


>  これはダミーを入れて偶数アドレスになるように調整しました。

実際のソースを見ないことには推測の域を出ませんが、偶数アドレスに整列すべき構造体が奇数アドレスに配置されるのは、#pragma pack等の方法で意図的にそうしているからではないでしょうか?
だとすれば、必要があるからそうしているのであって、警告を消すためだけにダミーを挿入するのは非常に危険です。
    • good
    • 0
この回答へのお礼

 回答有り難う御座います。

 CPUはルネサスのH8系です。16ビット幅が基本のCPUです。
 奇数個の char データの後に int データが来ると奇数アドレス
に配置されてしまう。
 2バイト以上で出来ている int データは、奇数アドレスから配置
出来ません。CPUのハード的な仕様です。
 
 アセンブラですと .ALIGN 2 として、アドレスを偶数に切り直します。
 アセンブラで文字データの後にマシン語が入るときは、偶数に切り直す処理が必要です。
 0001番地にジャンプさせる命令を書くと、最下位ビットが無視されて0000番地にジャンプします。
 16ビットのレジスタに読み書きするのも同様で、0001番地から
16ビット単位で読み書きしようとすると、0000番地からの2バイトをアクセスします。

 1バイト長のcharが構造体の中で奇数個連続すると、このような問題が起こります。
 プログラマがこのような事情を知らず、int などの偶数バイト長のデータが奇数アドレスに配置されると警告が出て、偶数に配置するようにコンパイラが調整します。
 この警告が出るのは、CPUの事情を知らないプログラマのミスです。

お礼日時:2008/10/06 00:48

警告の意味が分からないまま、闇雲にコンパイラを黙らせることののみを目的とした修正は非常に危険です。


実際に担当した外注先に確認するか、それができなければ放置することをお勧めします。
    • good
    • 0
この回答へのお礼

 回答有り難う御座います。

>警告の意味が分からないまま、闇雲にコンパイラを黙らせることのみを目的とした修正は非常に危険です。

 警告の意味を知るために調べているのです。
 直せる警告ならば直したい。

 今までの警告は、次のような物です。
 「構造体の境界線が奇数アドレスになる」
 これはダミーを入れて偶数アドレスになるように調整しました。

 「使われていない変数がある」
 コメントアウトしました。

 適切な処置だと思いますが。


>外注先に確認するか、それができなければ放置することをお勧めします。

 外注先も面倒を見てくれない古いソフトを改造する必要が有り
調べているのです。 

お礼日時:2008/10/05 20:40

コンパイルオプションに伴う警告なのでソースコードを修正する必要はないでしょう。


HEWというのがどういうものかわかりませんが、統合開発環境ならコンパイルオプションは設定画面で設定すると思うので、そちらを確認しては?

それから、Googleで
「HEW C1300 (W) Command parameter specified twice」
で検索した結果の一番上のPDFを読むと、
「【注意事項】
 CHECK=* は複数指定可能ですが、この場合には、以下のウォーニングメッセージが出力されます。
 C1300 (W) Command parameter specified twice
 本ウォーニングメッセージは、無視して頂いて構いません。」
とありますが、これとは別の話ですかね?
    • good
    • 0
この回答へのお礼

 有り難う御座います。
 僕ももう少し調べてみます。

お礼日時:2008/10/05 20:21

> コンパイラオプションが分からなくて質問したのですが。



最初の質問の文面からは、そういう意図は読み取れませんでした。
ところで、コンパイラーは何をお使いですか?
また、どういう風にコンパイルしていますか?
    • good
    • 0
この回答へのお礼

 有り難う御座います。

 ルネサスのH8マイコン用のHEWと言うソフトを使っています。
 扱い方については殆ど分かっていません。

 外注先が作った古いソフトを見ています。ワークスペースを
開いて、「コンパイル、ビルド、全てをビルド」をいじっています。
 
 構造体でchar変数が奇数個のため警告が出たので、ダミーを
入れて直したりしています。
 直せる警告を潰したいと思っています。

 ファイル内のプログラムを削除して行って、エラーが消えれば
場所が特定出来ると思って調べています。
 そこを調べれば警告の意味が分かると思っていました。

 コンパイルコマンドは中間ファイルを作るだけでリンケージまでは
しないと想像しています。

 コンパイルでもビルドでも同じエラーが出ます。
 何も書いてないファイルをコンパイルすれば、前述のエラーは消える
と想像しています。

 予想に反して消えないので、警告の意味が分からず皆様に
お聞きした次第です。
 宜しくお願いします。

お礼日時:2008/10/05 16:03

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!