• ベストアンサー

(void)0 はどんな意味ですか

 assert.h を見ると、次のように書かれています。 #define assert(x) ((void)0)  文法的に (void)0 どのように解釈出来るのでしょう。  次のプログラムで試すとエラーにもならず、コンパイラ結果を見ると何もしていないのが分かりました。 void main(void) { (void)0 ; }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

> 文法的に (void)0 どのように解釈出来るのでしょう。 文法的には,単純に,0をvoid型にキャストしているだけです。 cast-expression: (void)0 as '(' type-name ')' cast-expression  type-name: void  cast-expression: 0 as unary-expression   unary-expression: 0 as postfix-expression    postfix-expression: 0 as primary-expression     primary-expression: 0 as constant そして,void型への型変換は,規格 (ISO/IEC 9899:1999) の 6. Language - 6.3 Conversions - 6.3.2 Other operands - 6.3.2.2 void に説明があり, > If an expression of any other type is evaluated as a void expression, its value or designator is discarded. と書かれています。 つまり,値0は単純に破棄されます。 ちなみに,全ての式文は,6.8.3 Expression and null statementの第2段落に > The expression in an expression statement is evaluated as a void expression for its side effects. とあるため,voidへのキャストがあるかのように扱われます。

ricardo_
質問者

お礼

 回答有り難う御座います。  詳しいですね。規格を此処まで熟知している人は少ないと思います。  頼りになります。  英語の勉強にもなりました。  また質問したときには、宜しくお願いします。

その他の回答 (2)

  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.3

C言語では、関数呼び出しも代入計算も、基本的に全ての文は「式」に「;」を付けたものになっています。 「func();」という文は、「func()」という式を文にしたものになります。 「b=a+1;」という文は、「b=a+1」という式を文にしたものになります。 同じように、「0;」という文は、「0」という式を文にしたものになります。 ただし、このままだと数式の値を何にも利用していませんから、 コンパイラはバグの可能性を考えて「式の結果を利用していない」という警告を出す場合があります。(例えば、「a+1;」も文としては正しいですが、何の意味もない式文ですので、記述者が間違えている可能性が高いと推測できます) そこで、「0」という式をvoidにキャストする「(void)0」にすると、式の値を使っていないことを明示できるため、そういう警告を出さないようにできるのです。 では、非デバッグ時にassertの定義がなぜこのような形になっているかというと、 if (foo) assert(bar); といった形でassertが使われた時に、assert の効果は無くしつつも、assertを式として成立させて、if文としての体裁は変わらないようにしているのです。

ricardo_
質問者

お礼

 早速の回答有り難う御座います。  mtaka2さんの回答を見て下記のプログラムで試した所、コンパイラからは警告もエラーも有りませんでした。  ルネサスのマイコン用コンパイラHEWを使っています。  MISRA C と言うC言語のチェッカでは次の警告が有りました。 0 ; 何の副作用も無いという警告有り 1 == 1 ; 何の副作用も無いという警告有り (void)0 ; 何の副作用も無いという警告有り if (1)  ; {}を付けた方が良いと言う警告有り if (1){} ; 警告無し if (1){(void)0;}; 何の副作用も無いという警告有り  (void)0 を使えば警告は出なくなる事を期待したのですが、出るようです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「void へのキャスト」は「評価した値を使わない」ことを明示することになります. 「関数呼び出しや副作用を一切持たない式文にたいして警告を出す」処理系においては, 「void にキャストする」ことでそのような警告を抑制することができます.

ricardo_
質問者

お礼

 いつも回答有り難う御座います。  void と同じように無い事を明確にする訳ですね。  int から long にキャストする例は見かけますが、void にキャストしたらエラーかポインタような感じがしますよね。

関連するQ&A

  • int main()、void main()、void main(void)、int main(void)

    今日、大学でC言語の講義の時間、先生が、 #include <stdio.h> void main(void){ } と宣言してプログラムを書くと教えていました。 main関数には、 main() void main() void main( void ) int main() int main( void ) と、人によりいくつかの描き方があったりします。 どれが本当は正しいのでしょうか? void mainはすべきではないとなんかの本で読んだのですが・・。

  • int void (main)の意味・・・

    僕が今習っている学校では、『#include <stcio.h>』のあとに『void main()』と書きます。※『;』はつけません。 しかし、参考書などを見ると、『int main(void);』と書いてあります。これ(int main(void))はどういう意味なのかが知りたいのですが・・・。 あとできれば、『void main()』との違いも書いてくれれば幸いなのですが・・・。 回答お願いします。

  • void main (void)について、、、

    またまたすみません。 プログラムを書くときに、   void main (void)   と、とりあえず最初にこれを書く、と覚えていて意味がわかりません。 小学生でも理解できるくらいに噛み砕いて説明をお願いします。

  • Cプログラミングについて

    私はBorlandのコンパイラを使ってCプログラミングをやっているのですが、以下のプログラムが実行できません。 どのようにすればコンパイラできるのか教えてください。 非線型方程式f(x)=x^3-x+1の根をニュートン法により求めよ。 /* *-------------------------- *   ニュートン法 * *-------------------------- */ #include <stdio.h> #include <math.h> #define f(x) ((x)*(x)*(x)-(x)+1) #define g(x) (3*(x)*(x)-1) #define EPS 1e-8 #define LIMIT 50 int main(void) { double x=-2.0,dx;   int k; for (k=1;k<=LIMIT;k++){ dx=x; x=x-f(x)/g(x); if(fabs(x-dx)<fabs(dx)*EPS){ printf("iteration=%d\n",k); printf("x=%f\n",x); break; } } if (k>LIMIT) printf("収束しない\n"); } コンパイルしようとすると以下のようなエラーが出ます。 エラー E2206 sample.c 18: 不正な文字 ' ' (0x8140)(関数 main ) エラー E2206 sample.c 18: 不正な文字 ' ' (0x8140)(関数 main ) 警告 W8070 sample.c 32: 関数は値を返すべき(関数 main ) *** 2 errors in Compile *** お答えよろしくお願いします。

  • #defineで置き換えられない

    C言語です。詳しい方、よろしくお願いします。 下記のプログラムをコンパイルして実行したら、画像のようになってしまいます。 コンパイラは、CPad for LSI C-86 ver2.31です。 #include<stdio.h> #define clr() printf("\x1b[2J") void main(void) { while(1){ clr(); printf("test"); } } #defineがどうも置き換えられていないようです。 詳しい方、考えられる原因を教えてください。 よろしくお願いします。

  • C++の組込みマクロのassert()が使えない

    こんにちは。 CygwinでC++開発を行っているのですが、C++の関数型マクロであるassert()が使えなくて困っています。 main関数を含むソースファイルに、 #include assert.h を記述しておけば使えるはずなのですが、そのソースファイルから実行ファイルを、 g++コマンドでビルドしようとすると、以下のようなエラーが出ます。 ------------------------------------------------------------ $ g++ test03-STLの使用.cpp /cygdrive/c/Users/Kei/AppData/Local/Temp/cckwDP4e.o:test03-STLの使用.cpp:(.text+0x904): undefined reference to `___assert_func' collect2: ld はステータス 1 で終了しました ------------------------------------------------------------ test03-STLの使用.cpp のmain関数は、以下の通りです。 ------------------------------------------------------------ int main() { string s="ABC DEF\nGH\tIJ"; reverse(s.begin(), s.end() ); assert(s=="JI\tHG\nFED CBA"); cout<<s return 0; } ------------------------------------------------------------ ちなみに、実際にインクルードされる /usr/include/assert.h の内容は以下のようになっていました。 ------------------------------------------------------------ /* assert.h */ #ifdef __cplusplus extern "C" { #endif #include "_ansi.h" #undef assert #ifdef NDEBUG /* required by ANSI standard */ # define assert(__e) ((void)0) #else # define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \ __ASSERT_FUNC, #__e)) # ifndef __ASSERT_FUNC /* Use g++'s demangled names in C++. */ # if defined __cplusplus && defined __GNUC__ # define __ASSERT_FUNC __PRETTY_FUNCTION__ /* C99 requires the use of __func__. */ # elif __STDC_VERSION__ >= 199901L # define __ASSERT_FUNC __func__ /* Older versions of gcc don't have __func__ but can use __FUNCTION__. */ # elif __GNUC__ >= 2 # define __ASSERT_FUNC __FUNCTION__ /* failed to detect __func__ support. */ # else # define __ASSERT_FUNC ((char *) 0) # endif # endif /* !__ASSERT_FUNC */ #endif /* !NDEBUG */ void _EXFUN(__assert, (const char *, int, const char *) _ATTRIBUTE ((__noreturn__))); void _EXFUN(__assert_func, (const char *, int, const char *, const char *) _ATTRIBUTE ((__noreturn__))); #ifdef __cplusplus } #endif ------------------------------------------------------------ Borland C++ Compilerのbcc32コマンドでは、先ほどのソースファイルから実行ファイルをビルドすることができたので、何が問題なのかが分かりません。 以上の件について何かご存知の方がいらっしゃれば、是非教えて頂きたいと思います。 では、よろしくお願い致します。

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • C言語 配列の確保

    はじめまして。C言語の勉強を最近始めたのですが、 以下のプログラムで教えていただきたい点があります。 #include <stdio.h> #include <math.h> #define x 10000 #define y 200000 #define z 1.0E-12 #define k 1.38 #define kE 1.0E-23 #define h 6.63 #define hE 1.0E-34 #define c 3.00 #define cE 1.0E+08 void main(void){ int i; double A[x+1]; double B[x+1]; for(i=0;i<=x;i++) { A[i]=(i+y)*z; B[i] = exp(-(h*hE*c*cE)/(A[i]*k*kE*1000)); printf("%e %e\n",A[i],B[i]); }} このプログラムで、xを100000にするとプログラムが動かなくなってしまいます。OSはWindowsXP、ソフトはVisual C++ 6.0を使っています。 解決方法を教えていただけないでしょうか。

  • プログラムの最適化について質問です。

    プログラムの最適化について質問です。 /* 課題7 */ #include<stdio.h> #define A n /* n=10^0~9 */ void main() { int a,x; for(a=0;a<A;a++){ x=x+1; } } /* 課題8 */ #include<stdio.h> #define A n /* n=10^0~9 */ void main() { int a,x; for(a=0;a<A;a++){ x++; } } 課題7に比べて課題8の記述のメリットとして、単にソースコードを短くできる以外に、何が考えられるか。 という質問に対しての答えが分かりません。解説お願いします。

  • 結果を報告しない?(void)

    #include<iostream> #include<string> using namespace std; void Aisatu(string n){ cout<<n<<"さん、こんばんわ"<<endl; } int main() { Aisatu("鈴木"); } 上のプログラムで、C++の学習書に「void」とは「この関数は結果をどこにも報告しない、ということ」と書いてありますが、私の理解では下のAisatu("鈴木");という外部の文字列を受け取りcout<<nに「報告」しているように感じられます。どうか解釈がうまくいきますようにご教授いただけないでしょうか。よろしくお願いします。

専門家に質問してみよう