• 締切済み

未使用引数の注意文出力を回避するには

他種CPUの古いCソースをSH版に移植中なのですが、日立SHCコンパイラの オプション -ME でメッセージ出力抑制を解除すると大量の注意文が出力されて対処に 困っています。 その中で、C0012 (I) Unused variable "~" について、関数の取り合い仕様で引数が規定されているが、関数内処理では使われない 場合に注意文の出力を回避したいのですが、何かいい対策案ないでしょうか? int func( int a,int *b ){ return(0); } これまで分かっていることは 1)コンパイラは出荷済み他製品と共通なのでバージョンを上げられない。 2)-NOME=12 の出力抑制オプションは自動変数の未使用も検出しなくなるので不可。   (コンパイラも現状バージョンは番号指定に未対応です) 3)return(0); の後ろに a=0;b=0; と入れるとC0003 (I) Unreachable statementが出る。 4)変数属性の unused はコンパイラが未対応。 対策案の一つとして、関数内に if(a==0){} if(b==0){} を入れるというのがあるのですが、余分な機械語を生成しないか不安で検討中です。

みんなの回答

回答No.7

int func(int, int *) { return(0); } ではダメですか? C++なら通るので、もしかしたら通るのではないかと思うのですが。 #既にお試しでしたらご寛恕願います。

matyrcry
質問者

お礼

ありがとうございます。 C2137 (E) Null declaration for parameter で通さないらしいです。(しくしく

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.6

最後に可能性があるとすれば、 __inline void f() {} というインライン関数を定義して、f(a)とかf(b)のように、実引数として渡したということにするぐらいしかないですね。 関数原型がないので、どんな型でも渡せますし、関数定義側では仮引数を記述していないので未使用云々の警告も出ないはずです。また、普通に最適化されれば、何一つ命令は発生しないはずです。 ただし、実引数と仮引数の数が一致しないので、規格上は動作が未定義になります。未定義にならないようにするには、 __inline int f(int arg, ...) { return arg; } ですかね。これで (void)f(0,a) なら、コンパイラや静的検証ツールの警告は黙らせそうです。機械語が生成されるかどうかは微妙ですが...。

matyrcry
質問者

お礼

ありがとうございました。 インライン展開部を最適化して機械語が消滅すると注意文が出ました。 結局、引数を使用するための対策コーディングは可能だが、追加した コードが機械語を生成しなければ、別の注意文が出てしまうという話 のようですね。

全文を見る
すると、全ての回答が全文表示されます。
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★回答者 No.3 です。 ・カッコはマクロの引数が式だった場合に1つの式と評価させて代入させるためです。  それ以外は特に意味はありません。 ・それで、『UNREFERENCED_PARAMETER』マクロ関数が『WinNT.h』で定義されているので  覗いてみましたら次のような定義になっていました。 #if !defined(lint) #define UNREFERENCED_PARAMETER(P) (P) #else // lint // Note: lint -e530 says don't complain about uninitialized variables for // this varible. Error 527 has to do with unreachable code. // -restore restores checking to the -save state #define UNREFERENCED_PARAMETER(P)\  /*lint -save -e527 -e530 */\  {\   (P) = (P);\  }\ /*lint -restore */ #endif // lint ・定義内容を見ましたら『lint』が定義されていないと  『#define UNREFERENCED_PARAMETER(P) (P)』を定義して、『lint』があれば  『#define UNREFERENCED_PARAMETER(P) {(P)=(P);}』と定義するようです。 ・他にも似たようなマクロが定義されていました。  『#define DBG_UNREFERENCED_PARAMETER(P)    (P)』  『#define DBG_UNREFERENCED_LOCAL_VARIABLE(V) (V)』 ・となっていたので『UNREFERENCED_PARAMETER』マクロ関数は  『#define UNREFERENCED_PARAMETER(P) (P)』と定義してみたらどうでしょう。 ・以上。おわり。→試してみて下さい。

matyrcry
質問者

お礼

ありがとうございます。 ...結果は同じでした。(しくしく GNUだとunused宣言できるようですし、マイクロソフトさんもそれで抑制できるように してるんでしょうね。 ということで、今候補に考えているのは(面倒なんだけど)、メイクファイルを2つ作り、 コンパイルオプション -define=~=~ でソースに異なる引数を与えて条件コンパイル するという案です。 コーディング中のコンパイルでは、注意文対策を有効にして注意文全般は出力許可する。 ( -defineDBG_CHK=1 -me ) 実働用のコンパイルでは、注意文対策をコメントアウトして注意文全般は出力抑制する。 ( -defineDBG_CHK=0 -nome ) でソースに #if DBG_CHK if(a){} if(b){} if(c){} if(d){} #endif こんな感じです。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

lint的には /* ARGSUSED */ ってコメントを入れておくんだけど....

全文を見る
すると、全ての回答が全文表示されます。
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★私も回答者 No.1 さんと同じです。 ・『return』文よりも前に『a=a;』、『b=b;』の代入式を記述すれば警告メッセージは出なくなります。 ・私は『UNREFERENCED_PARAMETER』マクロを使っています。  UNREFERENCED_PARAMETER( a );  UNREFERENCED_PARAMETER( b );  と使います。→『日立SHCコンパイラ』にこのマクロがあるか分かりませんが、あれば利用しましょう。  機能は『a=a;』や『b=b;』と同じです。 ・よって、ない場合はご自分で #define 定義すれば今後の環境に移植しやすいと思います。  #define UNREFERENCED_PARAMETER(c) (c=(c)) ・また、代入文として機械語に展開される事を気にしているようですが、コンパイラの最適化の処理で  最近のコンパイラは展開されることはないと思います。→昔、MSC Ver.6.0 を使っていましたがアセンブラ出力  のオプションで展開後のファイルを出力したとき、『a=a;』や『b=b;』の代入式は展開されていませんでした。  昔から、未使用変数の警告メッセージはうっとうしいので『a=a;』などと記述していましたが、Win32 API 環境で  『UNREFERENCED_PARAMETER』マクロを見つけてからはずっと利用しています。 ・以上。未使用変数の対策アドバイスでした。

matyrcry
質問者

お礼

ありがとうございます。 ANo.1の時のお礼に追記が漏れていたことをお詫びします。 a=a;を記述すると、ANo.2のお礼と同様に、コードを生成しない行に関する メッセージが出力されます。 最適化オプションを変えながらアセンブラ出力を眺めてみましたが、 最適化オプションを入れても抜いてもa=a;はコード展開されませんでした。 御指南されたマクロ定義も、SHCにはなかったので#defineしてみましたが 同じ結果でした。 ところで#defineの置換先に付いている括弧は何か意図があるのでしょうか?

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

オプション等でどうにかするのであれば、-MEを止めるのが妥当なような気もします。 # たぶん、止められない理由があるのでしょうが... > 対策案の一つとして、関数内に > if(a==0){} if(b==0){} > を入れるというのがあるのですが、余分な機械語を生成しないか不安で検討中です。 コンパイル結果を見て確認するしかありませんが、将来、(今回のように)他の環境に移植する可能性なども考慮すると、確実性は乏しいですね。 とりあえず関数内に式を書いて何とかするのであれば、 (void)sizeof(a); (void)sizeof(b); とすれば余計なコードが生成される可能性はまずありませんが、このような対策はあまりお勧めできません。それに、今回の警告は出なくなっても、別の警告が出るかも知れませんし、コンパイラは寡黙になっても、外部の静的検証ツールが騒ぎ出す可能性もあります。 やはり、-MEを止めるか、警告は出たままにする方がよいと思います。

matyrcry
質問者

お礼

ありがとうございます。 C0010 (I) Elimination of needless expression (不要な式)が出ました。(しくしく 「これが出ない=コードが生成される」だとだめっぽいですね。 >止められない理由 コメントネスティングと上に書いた自動変数の未使用などは記述ミスで 起きる可能性が高いので、できればチェックとして利用したいのです。

全文を見る
すると、全ての回答が全文表示されます。
noname#26650
noname#26650
回答No.1

> 注意文の出力を回避したい return の「前」(後ろに何を書いても無意味です)に、 a = a; b = b; という、一見無意味なような、それでいて引数はちゃんと使っているような、 そんな文を書いてみてはどうでしょうか。

matyrcry
質問者

お礼

ありがとうございます。 その行が代入文として機械語に展開され処理時間を浪費するのを避けたいので、 どう記述すればどう展開されるか検証してみます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C言語の関数の仮引数の記述

    関数の仮引数の( )の中に何の変数を書いたらいいかいまいちつかめていません。関数の実行文や、もしくはmain関数の呼び出し実行文とどんな互換性があってどの変数を書いていいかわからないので教えてください。一応わかる部分を少し書きますがたとえば、変数をコピーするint copy( int a, int b )ってゆーのがあるとすれば、bをaにコピーするために必要となる変数a、bを( int a, int b )と書けばいいと思うんですがどうでしょう?仮引数部分にはmain関数に返す値となる変数だけを書くとどうなるんでしょう? なんかわかりにくくてすいませんが、答えになってなくても関係することであれば返信ください。 あとコンパイラーはCygwinで、理解度はfor文やif文や関数、配列などの基本はだいたいOKです。ポインタとかその他の応用についてはわかりません。

  • 引数のみで出力

    問題として main内部を変更してはならない。 関数sub()でmainのループと同じ出力するようにせよ。 ただし、関数subで引数以外の変数を宣言してはならない。 また、広域変数を追加してはならない。 となっていて、色々とforループで出力させようと 配列にしたりポインタにしたりしたのですが forのiに比例する配列をどう組めばいいのか、わからないです。。。 mainの出力は 1 8 15 22 29 36 となっています。 これをsubでもできるように設定するみたいです。 #include <stdio.h> #define MAX 7 void sub(int [MAX]); int main() { int i; int x[MAX]; for (i = 0; i < MAX-1; ++i) { x[i] = 7*i+1; } x[MAX-1] = 0; for (i = 0; x[i] > 0; ++i) { printf("x = %d\n", x[i]); } printf("print again\n"); sub(x); return 0; } void sub(int a[MAX]) { // a[6]=0 // MAX 7 a[MAX-1]=0; for(a[MAX-1];a[MAX-7]<=MAX-1;++a[MAX-1]){ //a[MAX-1] = 7*a[MAX-1]+1; printf("a[%d] = %d\n",a[MAX-1],a[MAX-7]); } }

  • 関数の引数と実引数の取り扱いについて

    C言語初心者です. 関数の引数と実引数の取り扱いについて,教えていただきたいことがあります. 例えば,2変数の和を求める関数を考えると,以下のようになると思います. #include <stdio.h> double sum(double x, double y); int main(void) { double a, b, wa; a=2.0; b=3.0; wa=sum(a,b); return 0; } double sum(double x, double y) { double total; total=x+y; return total; } このとき,mainプログラムでは,a,bふたつの変数を定義しておいて,関数sumに入れて計算させているわけですが,mainプログラムで変数x,yを定義しておいて,以下のようなプログラムにするのはありでしょうか? 参考書などをみると,前者のように取り扱っているようなのですが,試しに後者で実行させてみても同じ結果となりました. #include <stdio.h> double sum(double x, double y); int main(void) { double a, b, wa; a=2.0; b=3.0; wa=sum(a,b); return 0; } double sum(double x, double y) { double total; total=x+y; return total; }

  • ポインタ引数をさらにポインタ引数に渡す方法

    ポインタ引数をさらに関数のポインタ引数として設定するには、 どうしたらよいのでしょうか? イメージとしては、 int 関数A(*a *b) { *a = 5; *b =3; 関数B(*a *b) } またポインタ引数の関数内で、 ポインタ指定せずに変数を使えるのでしょうか? int 関数A(*a *b) { a = 5; b =3; 関数B(*a *b) }

  • 階乗の出力について

    Cを勉強中の者です。再起コールを使った階乗計算の結果を出力するプログラムをつくったのですが、もし再起コール(関数 kaijyo)を使わずにfor文などを使って同じように、階乗計算を行いたい場合どのようにすればいいでしょうか? 以下がそのソースコードです。説明が不足であればまた付け加えますのでよろしくおねがいします。 #include <stdio.h> int kaijyo(int a); int main(void) { int a; a = kaijyo(6); printf("6! = %d\n", a); return 0; } int kaijyo(int n) { if(n == 1) return 1; else return n*kaijyo(n-1); /*これを使わずに6!の結果を出したい/* }

  • return文

    return文で、下記のような書き方を見つけたのですが、 これはどういう戻り値になるんですか? return(a == b); a・bは共にint型の変数です。

    • ベストアンサー
    • Java
  • if~else文の中にまたif~else文をいれるには。

     このプログラムを思うように実行したいのですが、できません。 コンパイルはできるのですが、警告が4つほど出て、結果も自分が思ってるのとは違います。 プログラムのどこを改善すべきか教えてください。 OSはWindows XPで、コンパイラはボーランドのフリーコンパイラを使用しています。 #include<stdio.h> int main(){ int a,b,c,d; printf("1か0を入力してください。\n"); scanf("%d",&a); if(a=0) { printf("2か3を入力してください。\n"); scanf("%d",&b); if(b=2){ printf("今まで合計は%dです。\n",a+b); } if(b=3){ printf("今まで合計は%dです。\n",a+b); } else { printf("指定した数字を入力して下さい。\n"); } } else if(a=1) { printf("あなたは%dを入力しました。\n",a); } else { printf("指定した数字を入力してください。\n"); } return 0; }

  • 試作クラス使用C++プログラムが動かない原因

    試しに作成した以下のプログラムにビルドエラーが発生し,困っているので質問しました. コンパイラは,「BBB *b」などクラスポインタ変数の部分がエラーと指摘しているのですが(他にも数か所ありますが…),間違っている理由が分からず困ってます. ご回答,よろしくお願い致します. ----------------------------------- #include <iostream> using namespace std; class AAA { public: // コンストラクタ AAA(){ b = new BBB( this ); } // デストラクタ ~AAA(){ delete b; } // メンバ変数 BBB *b; int i; // メンバ関数 void displayB(){ b->displayA(); } }; class BBB { public: // コンストラクタ BBB( AAA *a ){ this->a = a; } // デストラクタ ~BBB(){} // メンバ変数 AAA *a; int j; // メンバ関数 void displayA(){ printf( "%d\n", a->i ); } }; int main() { // 変数の定義 AAA a; // 変数の初期化 a.i = 2; a.b->j = 5; // 出力 printf( "%d\n", a.i ); a.b->displayA(); return 0; } -----------------------------------

  • printfの出力内の文字をdefineしたい

    defineで定義した内容をprintfしたいのですが、どうすればいいですか? 次のようなコードを書きましたがコンパイルが通りませんでした。 #define ALP2 B int main(){ printf("A"ALP2"C"); return 0; } 上記のコードで「ABC」という出力を得たいです。 できれば変数に代入してから出力というのは避けたいので、それ以外の方法がありましたら教えてください。

  • C++/Cこういうことは可能でしょうか?違う型の引数をとって同じようなことをする

    お世話になります。 C++の初心者です。 違う引数をとって同じ関数にいれて同じようなことをさせるというのは できるのでしょうか? コンストラクタの作成方法で可能?? 共用体で可能?? 例: 型の違う構造体A,Bがある。 構造体のメンバには同じstatusが存在する。 statusが1のときだけresultを+し値を返す。 typedef struct{   int status;   int b; } DATA_A; typedef struct{   int status;   int b;   int c; } DATA_B; int test(DATA_AかDATA_Bを引数でとる,int data_num){ //data_numはデータ数  int i=0;  int counter=0;  for(i=0;i<data_num;i++){   //DATA_AまたはDATA_Bのメンバstatusが1ならcounterを+する   if(DATA_A.status == 1){    counter++;   }  }  return counter; } 以上のような感じです。 引数の型が違う2つの関数を作ればできますが、 同じことをさせるので同じ関数で実現できないかなと思って 質問させてもらいました。 よろしくおねがいします。