- ベストアンサー
C言語のキャストについて
C言語のキャストについて こんばんわ、質問です。 『キャスト』と言われる型を合わせるルールがあると思います。 あれはコンパイラに 「違う型の変数への代入だけど、これは意図したことですよ」 ってことを分かってもらうための手段という認識でよろしいでしょうか? コンパイル後、実行時には変数の型情報は使われない(残ってない?)と 思っていますが、その道を極めている方、教えてください。 キャストが何に使われるのか知りたいです。
- みんなの回答 (9)
- 専門家の回答
質問者が選んだベストアンサー
キャストはC言語で型の変換を明示的に行うための手段ですね。また、(void)printf("hello");のように関数の返り値を利用しないことを明示するのにも使われます。 しかし、void*ができて以降、C言語では前者の目的でキャストを使う必要はないのではないと思います。仰る通り、前者の使用用途では「違う型の変数への代入だけど、これは意図したことですよ」ということにも使えます。でも、型変換は代入だけではなく関数の引数となる時も使われるので必ずしも代入とは限りません。 なお、C++と違ってC言語ではvoid*がすべてのポインタに明示的にキャストせずに行き来できるので、近頃はほとんど前者の目的でキャストをしていません。今すぐ使用例として思い浮かぶのはネットワークプログラムを書くときに使うこれくらいでしょう。 | bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) しかし、これもPOSIX.1準拠の書き方をすると不要ですから、今時キャストの出る機会は関数の返り値を利用しないことを明示するときくらいでしょうね。昔のmallocの返り値はchar*だったのでキャストが必要でしたが、今時mallocの返り値はvoid*なのでキャスト不要ですし、memmoveのsrc、dstともにvoid*ですし、pthread_createの各スレッド関数がもらう変数はvoid*ですから巷で見かけるキャストの多くは無駄にキャストしていると思います。むしろ、キャストを使ったプログラムを見たら変にC++にかぶれた人が書いたプログラムか、void*がなかった頃の古いプログラムか、単なるキャストの練習かと思ってしまいます。 キャストはC言語の機能でも強力な機能の一つで、下手に使うとコンパイラによる型チェックを壊してバクを見つけにくくするので使わないに越したことはないです。もし、どうしても使わないといけないとしたら設計が間違っていないかもう一度確かめたほうがいいと思います。 他の言語でもキャストは型チェックを弱める強力な言語機能であり、バグの温床なので避ける方向に行っていると思います。C++の場合、実務のコーディング規則ではC言語風の何でも変換できてしまうキャストは許可されないはずです。JavaでもGenericsをいれたあたりでキャストがなくてもほとんどのプログラムが書けるようになったと思いますしね。
その他の回答 (8)
- jacta
- ベストアンサー率26% (845/3158)
一応書いておくと... 関数原型(プロトタイプ)がない関数を呼び出す場合、実引数をキャストしても、既定の実引数拡張によって無意味になる場合があります。 具体的には、関数原型のない関数 foo を呼び出す際に、 foo((char)a, (char)b); のようにchar型にキャストしたとしても、既定の実引数拡張によって、各実引数は通常int型に暗黙的に型変換されます。 ただし、sizeof(char) == sizeof(int) かつ char型が符号無しの処理系では、int型ではなくunsigned int型に型変換されます。
- higeG
- ベストアンサー率22% (4/18)
プロトタイプ宣言の無い関数への引数の受け渡し時にもコンパイル結果が違ってきます。 例えば char foo(char a, char b) { return a + b; } と言う関数があった場合、他のソースからこの関数を呼び出す時にプロトタイプ宣言していないと int x, y; x = foo(1, 2); と呼び出すと期待した動きをしませんが、 y = foo((char)1, (char)2); だと正常に動きます。 ただ、キャストの問題というよりもプロトタイプ宣言は必ずしましょうという例ですが。
お礼
回答ありがとうございます!
- jacta
- ベストアンサー率26% (845/3158)
> そうすると疑問があります。 > ・objには各変数の型情報があるのでしょうか? > ・もしくはコンパイラに「この計算は浮動小数点型で行う」という意味で解釈され、 > 変換されるのでしょうか? > (浮動小数点演算という意味のアセンブラに変換されて、バイナリになる?) コンパイラの出力結果を調べてみるのが、一番納得できると思います。
- Tacosan
- ベストアンサー率23% (3656/15482)
「ふつ~のプロセッサ」だと, 整数演算と浮動小数演算とでは異なる命令です.
お礼
回答ありがとうございます。
- Tacosan
- ベストアンサー率23% (3656/15482)
POSIX 的にいえば, execl 系でキャストを必要とすることがありますな>#3.
お礼
回答ありがとうございます。 早とちりしました…。 追加で教えて頂きありがとうございます。
- jacta
- ベストアンサー率26% (845/3158)
> 「違う型の変数への代入だけど、これは意図したことですよ」 > ってことを分かってもらうための手段という認識でよろしいでしょうか? 違います。 もしそうだとすると、次のような例は説明がつきません。 int a = 1; int b = (double)a / 2 * 2;
お礼
回答ありがとうございます。 (double)a / 2 で左辺がdouble型であるため、1.0 / 2.0となり 結果が0.5になって、0.5 * 2で変数bは1になると思います。 そうすると疑問があります。 ・objには各変数の型情報があるのでしょうか? ・もしくはコンパイラに「この計算は浮動小数点型で行う」という意味で解釈され、 変換されるのでしょうか? (浮動小数点演算という意味のアセンブラに変換されて、バイナリになる?) どなたか教えてくださいませ。
- Tacosan
- ベストアンサー率23% (3656/15482)
厳密にいうとキャストは「型を変換する」ものであり, 「型を合わせるルール」ではありません.
お礼
回答ありがとうございます。 お詳しいのでしたら、よろしければ もう少し教えていただきたいです。
- YUI_AI
- ベストアンサー率45% (303/661)
「明示的な型変換」なのでその認識で宜しいかと思います。 参考までに http://msdn.microsoft.com/ja-jp/library/kca3w8x6.aspx
お礼
回答ありがとうございます。
お礼
詳しい回答ありがとうございます! C言語はメモリアクセスに歯止めが無い(笑)ので、 キャストの意味について悩んでおりました。