• 締切済み

何も書いて無いのに警告が出るだろうか

 プログラム解析のため10個ぐらいのC言語ファイルで 出来たソフトをビルドしたのですが、次の警告が最初の ファイル以外に対して、それぞれ出ます。 >C1300 (W) Command parameter specified twice > 同じコンパイラオプションを2度以上指定しています。 >同じコンパイラオプションの中で最後に指定したものを >有効とします。  define 等が2度以上書かれているのかなと思い、あるファイル の中身を全て削除しました。中身が空なだけでファイルは消して いません。  それなのに、そのファイルに対して上の警告が出ます。  この警告は何でしょう。何も書いて無いのにこのような警告が 出るのでしょうか。  宜しくお願いします。

みんなの回答

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.12

>  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は同じでもコンパイラの種類やバージョン、あるいはコンパイラオプションが変わっただけで型のサイズはかなり変わるのです。 それを無視してダミーを入れると、移植性を損なって将来に不安を残すだけですし、下手をすると今回も動かなくなります。

richardo
質問者

お礼

 こんにちは > 「構造体の境界線が奇数アドレスになる」 という警告が出たとおっしゃいました。  「構造体の境界線が奇数アドレスになるから、パディングして 偶数に揃えた。」  と言う事を言いたかったのです。すなわち次の警告の内容です。  「構造体のメンバ間に境界調整の空き領域を生成しました。」  言葉足らずだったこも知れませんが、此処に投稿してくれる 方には分かってくれると思っていたのですが。  以前にHC3048のアセンブラで、データを変更したため奇数バイト になったら、その後に書かれている命令が暴走しました。  マシン語が奇数番地から始まっていたからです。アセンブラも警告してくれないし、CPUも「ジャンプ先アドレスが奇数になっている」 と言うような事を知らせてくれる割り込みが用意されている訳でも 有りません。  プログラマが注意して境界管理をしなくてはいけません。 16ビット単位のデータの読み書きに対しては確認していま せんが、奇数アドレスですと同じようなエラーになるでしょう。  そんな訳で、コンパイラが境界管理をする前に自分で パディングして境界調整をするべきだと書いたのです。  色々と回答して下さるのは嬉しいのですが、脇道に深く入り 過ぎました。  当初の質問も皆様の温かい回答により、解決しました。  皆様、有り難う御座いました。  このパディングの話は、この辺で終わりにしませんか。

  • S117
  • ベストアンサー率40% (18/45)
回答No.11

横槍かつ横道ですが。 >「C0016 (I) Padding in structure >構造体のメンバ間に境界調整の空き領域を生成しました。」 は初出ですよね? 残念ながらそれ以前の文章からは >コンパイラに行わせるのでは無く、プログラマがダミーを >入れて認識しておくべきだろうと言っているのです。 は読み取れないのですが。 ここまでの文章では「何らかのオプションにより意図的に境界からずらしてコンパイルし、実際にずれた状態は修正されずコンパイルが行われている。」と読めます。そして、実際にずれた状態でコンパイルされていて、それで正常に動くのであれば、それを修正するのは危険です。 今回は単に「コンパイラが警告を出した上で調整」していたのを、「自分で調整」するようにしただけなので、正当な修正です。 ただ、PCの処理系の場合は普通は黙って境界調整します。通常警告が出る条件やメッセージは処理系に依存します。ですので、警告について正しい理解をするには、警告のメッセージそのものを見るしかありません。 ちなみに、バスエラーがでるかどうかは処理系依存でして。たとえばWindowsのVisual Cで試すと、 char arr[10]; int *p; p = (int*)(arr + 1); *p = 10; printf("%d", *p); これが動くんですね。

richardo
質問者

お礼

 有り難う御座います。  No.12でご返事とお礼に変えさせて頂きます。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.10

>  私の考えは、次のURLの最後に書いてある > 「構造体を設計するときは、このようにアライメントを考えた構造にするようにしましょう。」と言う事です。 そのサイトに書いている内容は、各データ型のサイズを仮定している時点で移植性がありません。 間違った情報を鵜呑みにするのはやめましょう。 そして、今回の場合は、意図的に構造体が奇数番地から始まる可能性があるような設定をしているわけですから、原則論ではなく、特殊な事情があると考えるのが妥当です。

richardo
質問者

お礼

 jacta さんは勘違いしていませんか。  int など偶数バイト単位で構成されるデータは、偶数番地にしか配置 出来ません。CPUの依存性が有ります。  パソコンのCPUだったら、32ビット単位だと思います。  それでコンパイラは次の警告を出し、1バイトの空き領域 を作り、偶数番地に配置するのです。 「C0016 (I) Padding in structure 構造体のメンバ間に境界調整の空き領域を生成しました。」  コンパイラに行わせるのでは無く、プログラマがダミーを 入れて認識しておくべきだろうと言っているのです。

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.9

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

richardo
質問者

お礼

 salsberry さん、及びNo4の 0x131cc6e さん、 有り難う御座います。  解決の糸口が分かりました。調べてみると、 -lang=c -nologo -sj -lan=c  と書いてあります。-lang=c と -lan=c が同じ意味で ダブっているのではと思い、-lan=c を削除したら 警告が消えました。  他にも「ケース文をIF文にした」と言うような警告が 出るのですが、「-case=table」にヒントが有りそうです。  どんなオプションが有るのか、それを解説してあるマニュアルが 有るか探してみます。  どうも有り難う御座いました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.8

> この警告が出るのは、CPUの事情を知らないプログラマのミスです。 断定はできませんが、おそらく違います。 Cコンパイラは、ハードウェアの仕様で16ビット以上の変数が偶数バイト境界に整列していなければならない場合、デフォルトでは勝手にそのように配置します。奇数バイトに配置するには、コンパイラオプションや#pragma指令などを使って、明示的に指定しなければなりません。 明示的に奇数バイトに配置しているということは、何らかの事情でそうすることが必要だということです。 ちなみに、#pragma packなどでint型を奇数バイトに配置した場合、コンパイラは上位バイトと下位バイトを分割して読み書きするコードを生成するなどの方法で対応することになるはずです。

richardo
質問者

お礼

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

回答No.7

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

richardo
質問者

お礼

 回答有り難う御座います。 >プログラムの内容が理解できないまま修正するのは危険です  理解するためにいじっているのです。まずは警告が出ないように まともなソフトに訂正したい。  警告の理由を調べているのです。 >可能であれば、開発環境をまるごと(ハードディスクのコピーとか)入手することをお勧めします。  外の会社で誰が作ったか分からないソフトを改造するのですから 無理ですね。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.6

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

richardo
質問者

お礼

 回答有り難う御座います。  CPUはルネサスのH8系です。16ビット幅が基本のCPUです。  奇数個の char データの後に int データが来ると奇数アドレス に配置されてしまう。  2バイト以上で出来ている int データは、奇数アドレスから配置 出来ません。CPUのハード的な仕様です。    アセンブラですと .ALIGN 2 として、アドレスを偶数に切り直します。  アセンブラで文字データの後にマシン語が入るときは、偶数に切り直す処理が必要です。  0001番地にジャンプさせる命令を書くと、最下位ビットが無視されて0000番地にジャンプします。  16ビットのレジスタに読み書きするのも同様で、0001番地から 16ビット単位で読み書きしようとすると、0000番地からの2バイトをアクセスします。  1バイト長のcharが構造体の中で奇数個連続すると、このような問題が起こります。  プログラマがこのような事情を知らず、int などの偶数バイト長のデータが奇数アドレスに配置されると警告が出て、偶数に配置するようにコンパイラが調整します。  この警告が出るのは、CPUの事情を知らないプログラマのミスです。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

警告の意味が分からないまま、闇雲にコンパイラを黙らせることののみを目的とした修正は非常に危険です。 実際に担当した外注先に確認するか、それができなければ放置することをお勧めします。

richardo
質問者

お礼

 回答有り難う御座います。 >警告の意味が分からないまま、闇雲にコンパイラを黙らせることのみを目的とした修正は非常に危険です。  警告の意味を知るために調べているのです。  直せる警告ならば直したい。  今までの警告は、次のような物です。  「構造体の境界線が奇数アドレスになる」  これはダミーを入れて偶数アドレスになるように調整しました。  「使われていない変数がある」  コメントアウトしました。  適切な処置だと思いますが。 >外注先に確認するか、それができなければ放置することをお勧めします。  外注先も面倒を見てくれない古いソフトを改造する必要が有り 調べているのです。 

  • 0x131cc6e
  • ベストアンサー率36% (42/115)
回答No.4

コンパイルオプションに伴う警告なのでソースコードを修正する必要はないでしょう。 HEWというのがどういうものかわかりませんが、統合開発環境ならコンパイルオプションは設定画面で設定すると思うので、そちらを確認しては? それから、Googleで 「HEW C1300 (W) Command parameter specified twice」 で検索した結果の一番上のPDFを読むと、 「【注意事項】  CHECK=* は複数指定可能ですが、この場合には、以下のウォーニングメッセージが出力されます。  C1300 (W) Command parameter specified twice  本ウォーニングメッセージは、無視して頂いて構いません。」 とありますが、これとは別の話ですかね?

richardo
質問者

お礼

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

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

> コンパイラオプションが分からなくて質問したのですが。 最初の質問の文面からは、そういう意図は読み取れませんでした。 ところで、コンパイラーは何をお使いですか? また、どういう風にコンパイルしていますか?

richardo
質問者

お礼

 有り難う御座います。  ルネサスのH8マイコン用のHEWと言うソフトを使っています。  扱い方については殆ど分かっていません。  外注先が作った古いソフトを見ています。ワークスペースを 開いて、「コンパイル、ビルド、全てをビルド」をいじっています。    構造体でchar変数が奇数個のため警告が出たので、ダミーを 入れて直したりしています。  直せる警告を潰したいと思っています。  ファイル内のプログラムを削除して行って、エラーが消えれば 場所が特定出来ると思って調べています。  そこを調べれば警告の意味が分かると思っていました。  コンパイルコマンドは中間ファイルを作るだけでリンケージまでは しないと想像しています。  コンパイルでもビルドでも同じエラーが出ます。  何も書いてないファイルをコンパイルすれば、前述のエラーは消える と想像しています。  予想に反して消えないので、警告の意味が分からず皆様に お聞きした次第です。  宜しくお願いします。

関連するQ&A

  • mxmlcでのビルドの警告について

    Abobe Flush Builder 4.7 でビルドした場合と、 mxmlcでビルドした場合で、mxmlcでしか出ない警告があり困っています。 例えば、 var a:Function = null; if(a){} 上記のようなコードで、Flush Builderでは警告は出ませんが、mxmlcでは警告が出ます。 Flush Builderのコンパイラーオプションでは、 ・厳密な方のチェックを有効にする ・警告を有効にする 上記は音になってます。 mxmlcの方は、特に警告などに関するオプション(-strict -warnings等)は指定していません。

  • テキストファイルを開く度に警告が出る

    すみません、教えてください。 WindowsUpdateをかけたためか、 急にテキストファイルを開く度に警告が出るようになってしまいました。 ExcelやWordは大丈夫なのですが、テキストファイルだけ、警告が出ます。 警告はバッチファイルを編集するときのようなやつです。 また、自身のPC内のファイルであれば、警告は出ないのですが、 社内ネットワーク上のファイルだと出てしまいます。 自分で調べ、Explorer→インターネットオプション→セキュリティ→ローカルイントラネット→サイト→詳細設定から、 社内ネットワークのサーバを指定したのですがダメでした。。 どなたかご教授ください。 よろしくお願いします。

  • GCCで暗黙の型変換の警告を出したい

    情報が失われてしまうような代入について警告を出したいのですが、 どういったオプションを用いればよいでしょうか? コンパイラはGCCの3.x系か4.x系でお願いします。 以下のようなソースで型変換に関する警告がほしいんです。 --- test.c --- #include <stdio.h> int main(void) {   int a = 66000;   short b;   b = a; // <- 暗黙の型変換   printf("%d\n", b);   return 0; } 実行結果 $ ./test 464 以下のオプションを試しましたが、上記のソースでは 何の警告も出ませんでした。 -W -Wall -Wconversion -Wimplicit ご存知の方いらっしゃいましたら、どうかお助け下さい。

  • 起動のたびに警告文が出る。

    OSはWindows Meですが、起動のたびに次のような警告文が出ます。「ファイル'c:\a.tmp'が見つかりません。システムにファイルが存在するか、パスおよびファイル名が正しいか確認してください。」です。プログラムの中のスタートアップにはそれに関したものはありません。また、「ファイル名を指定して実行」からmsconfigを入力して、スタートアップの項目を見てもそれらしきものはありません。どうすれば出なくなるでしょうか。教えてください。お願いします。

  • define文のパラメータを実行時に変化させたい

    Cで、define文で値を指定することがあると思います。 シェルスクリプトあたりを使って、define文で指定される定数のパラメータを変化させて、自動でパラメータを変化させてデータを取りたいです。 そのようなときにはどのように記述すればよいのでしょうか? たとえば、下のような場合です。 環境はlinuxです。 よろしくお願いします。 //////////////////////////////////////// #define LOOP 400 <---- ここを実行時に変化させたい。 #define FILESIZE LOOP*16 int main(int argc, char** argv){ printf("FILESIZE = %d\n", FILESIZE); }

  • VC++の/Zm オプションについて

    仕事でVC++で開発されたソフトに機能追加をしています。 環境はVisualC++6.0(SP3)&Win2Kです。 何年か前に開発されて他の人がやってたものを今回引き継ぎました。 SDKで開発しているソフトなのですが、グローバル変数が かなり多いです。おそらくそれが原因と思われますが、 今回の機能追加の途中でビルド時にエラーが出るように なりました。 (致命的なエラー C1076 コンパイラの制限 : 内部ヒープ領域の上限に達しました。領域を広げるには、/Zm オプションを使ってください。) 調べてみたところ、/Zm コンパイラオプションで コンパイラのメモリ アロケーションの領域を設定するとよいみたいでした。 ひとまず/Zmが150になっていたものを160に設定してビルドは通るようになりましたが、気がかりな点があります。 コンパイラオプションを変えることによって、何か弊害が でることはあるのでしょうか。 今回のコンパイラオプションを変えたことが原因で不具合があってはと思いまして・・・ VC++初心者なのですごく初歩的な質問をしているかもしれません。どなたか教えてください。

  • 起動時の警告

    PCを起動した時に、RUNDLLという警告が出て C:\WINDOWS\IMAGE.DLLを読み込み中にエラーが発生しました。 指定されたファイルが見つかりません と同じ物が2つ出てきます。 特別何かしたつもりはないのですが、ある時から出てくる ようになりました。 どなたか、対処法をおしえていただけませんでしょうか? 原因もわかれば助かります。

  • Cygwinに付属しているg++コマンドについて

    こんにちは。 Cygwinに付属しているC++コンパイルコマンドのg++について、いくつか質問させて下さい。 ・g++はC++だけでなく、Cのソースファイルもコンパイルできるので、Cのプログラムを開発するときは、gccは必要なく、g++だけでよいと思うのですが、どうしてgccが存在するのでしょうか? g++だけで十分ですよね? ・bashなどのコマンドライン上で g++ -print-libgcc-file-name と入力すると、コンパイラのコンパニオンライブラリ名を表示されるようなのですが、 コンパイラライブラリって何なのでしょうか? ちなみに自分の環境では、 /bin/../lib/gcc/i686-pc-cygwin/4.3.4/libgcc.a と表示されました。 ・-timeオプションを付けてg++でCソースファイルをビルドすると、以下のようになりました。 $ g++ -time "test.c" # cc1plus 0.03 0.01 # as 0.00 0.01 # collect2 0.00 0.08 1つめの時間と、2つめの時間は、それぞれ何を意味するのでしょうか? ・g++で使えるコマンドラインオプションとgccで使えるコマンドラインオプションは、 一緒のような気がするのですが、g++でしか使えないコマンドラインオプションってありますか? 以上です。 よろしくお願い致します。

  • ローカルディスクDの警告を消すには

    普段はCを使っているので、Dにはほぼ満タンにファイルなどを入れておいているんですが、起動するたびにタスクトレイに”空き容量が少なくなっているのでいらなくなったファイルを削除して下さい”と警告がでて、毎回それを消すのに苦労しています そこでこの容量不足の警告自体を消す方法はないでしょうか? winxpですよろしくお願いします

  • Cのソースファイルにすると警告が出る理由

    wavファイルを再生するプログラムを勉強中なのですが、下のプログラムをビルドすると error C2055: 型リストではなく、仮パラメーター リストが必要です。 warning C4047: '関数' : 間接参照のレベルが 'MCIDEVICEID' と 'void *' で異なっています。 warning C4024: 'mciSendCommandW' : の型が 1 の仮引数および実引数と異なります。 という警告が出ます。 いろいろ試した結果、ソースファイルの拡張子をcからcppに変更したら警告が消えたのですがどうして拡張子がCのソースファイルでビルドすると警告がでるのか理由が全く分かりません。 拡張子を変更しないで警告を出さないようにするにはどこを直せばいいのでしょうか? --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語 #include<Windows.h> #include "resource.h" #include<MMSystem.h> #pragma comment(lib,"winmm.lib") HINSTANCE hinst; INT_PTR CALLBACK dlgproc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int nCmdShow) { hinst=hInstance; DialogBox(hinst,TEXT("mydlg"),NULL,dlgproc); return 0; } INT_PTR CALLBACK dlgproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) { static MCI_OPEN_PARMS mop; static MCI_PLAY_PARMS play; switch(msg) { case WM_INITDIALOG: mop.lpstrDeviceType=TEXT("WaveAudio"); mop.lpstrElementName=TEXT("C:\\Users\\test.wav"); mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,(DWORD_PTR)&mop); mciSendCommand(mop.wDeviceID,MCI_PLAY,NULL,(DWORD_PTR)&play); return (INT_PTR)TRUE; case WM_CLOSE: EndDialog(hwnd,LOWORD(wp)); return (INT_PTR)TRUE; break; } return(INT_PTR)FALSE; }

専門家に質問してみよう