• ベストアンサー

C言語のキャストについて

C言語のキャストについて こんばんわ、質問です。 『キャスト』と言われる型を合わせるルールがあると思います。 あれはコンパイラに 「違う型の変数への代入だけど、これは意図したことですよ」 ってことを分かってもらうための手段という認識でよろしいでしょうか? コンパイル後、実行時には変数の型情報は使われない(残ってない?)と 思っていますが、その道を極めている方、教えてください。 キャストが何に使われるのか知りたいです。

noname#150259
noname#150259

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

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

キャストは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をいれたあたりでキャストがなくてもほとんどのプログラムが書けるようになったと思いますしね。

noname#150259
質問者

お礼

詳しい回答ありがとうございます! C言語はメモリアクセスに歯止めが無い(笑)ので、 キャストの意味について悩んでおりました。

その他の回答 (8)

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

一応書いておくと... 関数原型(プロトタイプ)がない関数を呼び出す場合、実引数をキャストしても、既定の実引数拡張によって無意味になる場合があります。 具体的には、関数原型のない関数 foo を呼び出す際に、 foo((char)a, (char)b); のようにchar型にキャストしたとしても、既定の実引数拡張によって、各実引数は通常int型に暗黙的に型変換されます。 ただし、sizeof(char) == sizeof(int) かつ char型が符号無しの処理系では、int型ではなくunsigned int型に型変換されます。

  • higeG
  • ベストアンサー率22% (4/18)
回答No.8

プロトタイプ宣言の無い関数への引数の受け渡し時にもコンパイル結果が違ってきます。 例えば char foo(char a, char b) { return a + b; } と言う関数があった場合、他のソースからこの関数を呼び出す時にプロトタイプ宣言していないと int x, y; x = foo(1, 2); と呼び出すと期待した動きをしませんが、 y = foo((char)1, (char)2); だと正常に動きます。 ただ、キャストの問題というよりもプロトタイプ宣言は必ずしましょうという例ですが。

noname#150259
質問者

お礼

回答ありがとうございます!

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

> そうすると疑問があります。 > ・objには各変数の型情報があるのでしょうか? > ・もしくはコンパイラに「この計算は浮動小数点型で行う」という意味で解釈され、 > 変換されるのでしょうか? > (浮動小数点演算という意味のアセンブラに変換されて、バイナリになる?) コンパイラの出力結果を調べてみるのが、一番納得できると思います。

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

「ふつ~のプロセッサ」だと, 整数演算と浮動小数演算とでは異なる命令です.

noname#150259
質問者

お礼

回答ありがとうございます。

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

POSIX 的にいえば, execl 系でキャストを必要とすることがありますな>#3.

noname#150259
質問者

お礼

回答ありがとうございます。 早とちりしました…。 追加で教えて頂きありがとうございます。

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

> 「違う型の変数への代入だけど、これは意図したことですよ」 > ってことを分かってもらうための手段という認識でよろしいでしょうか? 違います。 もしそうだとすると、次のような例は説明がつきません。 int a = 1; int b = (double)a / 2 * 2;

noname#150259
質問者

お礼

回答ありがとうございます。 (double)a / 2 で左辺がdouble型であるため、1.0 / 2.0となり 結果が0.5になって、0.5 * 2で変数bは1になると思います。 そうすると疑問があります。 ・objには各変数の型情報があるのでしょうか? ・もしくはコンパイラに「この計算は浮動小数点型で行う」という意味で解釈され、 変換されるのでしょうか? (浮動小数点演算という意味のアセンブラに変換されて、バイナリになる?) どなたか教えてくださいませ。

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

厳密にいうとキャストは「型を変換する」ものであり, 「型を合わせるルール」ではありません.

noname#150259
質問者

お礼

回答ありがとうございます。 お詳しいのでしたら、よろしければ もう少し教えていただきたいです。

  • YUI_AI
  • ベストアンサー率45% (303/661)
回答No.1

「明示的な型変換」なのでその認識で宜しいかと思います。 参考までに http://msdn.microsoft.com/ja-jp/library/kca3w8x6.aspx

noname#150259
質問者

お礼

回答ありがとうございます。

関連するQ&A

  • C言語の型キャスト

    C言語入門者です、よろしくお願いします C言語の型キャストについて教えてください 参考サイトで以下のようになってました char str[8] = "ABC"; char *ptr; ptr = (char*)str; printf("char型ポインタのアドレス先の値は: %s\n", ptr); この型キャストって意味ありますか? キャストしようがしなかろうがptrに収まるのはstrの先頭アドレスですよね? ただ型キャストを説明するためだけにこのような形にしているのか 意味がある型キャストなのかが解らず迷ってます

  • C言語についてどうしてもわからない疑問

    プログラミング初心者です。 C言語を勉強中に疑問に思ったことが2つあります。 まず1つ目。 C言語以外のプログラミング言語、例えばjavaとかC#とかjsとかpythonとかrubyとかPHPとか、には開発者にとって便利なライブラリとかフレームワーク(僕にはこの2つの明確な違いがわかりません。が、どちらも「開発者が定義しなくてもよい関数やオブジェクトの集合」という認識があります)がありますよね。 そのおかげで色んな人達がプログラミングし易くなりました。 ネット(はてぶのホットエントリとか)でも「馬鹿な俺がプログラミングを勉強して〇〇を作った」といった記事をよく目にします。 でも「C言語を使って」というのは聞いたことがありません。 そもそも、C言語はそいういったライブラリやフレームワークが少ないように感じます。 検索してもrailsとかjqueryのようなフレームワーク(ライブラリ?)は見つかりません。 これが無かったらプログラムなんて作れないのでは? しかし、世間にはC言語で作られたプログラムが多いのもまた事実。 C言語ではいったいどのように開発が行われているのか教えてください。 2つ目 unixとかlinuxといったOSはC言語で書かれている聞いたことがあります。 しかし、プログラムの開発は「コードを書く→コンパイル(→デバッグ)→実行」という流れですよね。 ではOSを開発するときに、そのコードをどうやってコンパイルするのでしょうか? コンパイラはOSの上に立っているとするなら、OSがない状態でコンパイラはどこに立てばいいのか。 そこがわかりません。 誰かこの2つの疑問に答えてください。 お願いします。

  • C言語について

    最近C言語でプログラミングを試みようとしてるのですが、コンパイルの時点でよく分かりません。 どのようなソフトでどのようにインストール・設定し、どのようにコンパイルするかなど、C言語でのプログラムのコンパイルから実行までを詳しく教えてください。

  • C言語のキャストについて

    お世話になります。 CRC-16の計算プログラムをC言語でつくりました。 例えば・・・1F 08 00 00 12 34 なら“1F0800001234”と入力すると【EEC2】と表示するプログラムです。 ただ・・・.Net SDKでコンパイルするとできたのですが、Visual C++2008でコンパイルするとエラーが出てしまいます。 (48) : error C2664: 'strlen' : 1 番目の引数を 'unsigned char [256]' から 'const char *' に変換できません。(新しい機能 ; ヘルプを参照) 1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 (52) : error C2664: 'strtol' : 1 番目の引数を 'unsigned char [3]' から 'const char *' に変換できません。(新しい機能 ; ヘルプを参照) 1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 型変換が必要ってことまではわかったのですが・・・必要なのはわかって行き詰まり状態です。。。 どのようしたらよいのでしょうか?ご教授をよろしくお願いします。 ソースは以下の通りです。 #include "stdafx.h" #include <stdio.h> #include <string.h> #include <stdlib.h> unsigned short crc_cal(unsigned short lng, unsigned char *str) { unsigned short crc, i, j, t; t= 0x0000; crc = 0xffff; for (i = 0; i < lng ; i++) { crc ^= (unsigned short) str[i]; t = (unsigned short) str[i]; for (j = 1; j <= 8; j++) { if (crc & 1) { // carry bit on crc = crc >> 1; crc ^= 0xa001; } else { // carry bit off crc = crc >> 1; } } } return crc; } int main(void) { unsigned char str[256],data[128],hexstr[3]; unsigned short crc,CRC,len; while(1) { printf("Please input key (HEX)\n"); scanf("%255s",str); hexstr[2]='\0'; for(len=0; len<(strlen(str)/2) ;len++) { hexstr[0]=str[len*2]; hexstr[1]=str[len*2+1]; data[len]=(unsigned char)strtol(hexstr, NULL, 16); } crc = crc_cal(len,data); CRC = (crc>>8) | (crc<<8); printf("\nCRC16 = %04X\n\n", CRC); } return 0; }

  • C言語の参考書について

    大学の後期の授業でC言語の参考書を買ってくるように言われました。 でもどの参考書がいいのかわからないので教えてください!! 前期の授業では ・C言語で作成したプログラムのコンパイルと実行の 流れ ・コンパイルエラーのエラーメッセージの見方 ・実行時のエラーとプログラムの修正 ・C言語のプログラムの基本形 ・printf()と定数 ・変数 ・数値型 ・文字型 ・文字列 ・printf()の書式指定 ・プログラム記述時の約束、予約語 ・算術演算子 ・代入演算子 ・インクリメント、デクリメント演算子 ・比較演算子(関係演算子) ・式が持っている値 ・論理演算子 ・条件付き代入 を勉強しました。 その範囲は、まだちゃんとに覚えてないけど授業でもらったプリントを見れば一応できます。 それで先生いわく、参考書は入門編でもいいらしいんですけど、さらに実践編も買い足さなければいけないらしいんです。 今の状態で実践編でも大丈夫ですかねぇ??

  • C言語のコンパイラについて教えてください。

    C言語の勉強をしてるのですが、コンパイルすると普通にミスは認められず表示されたので、実行してみて入力とかしてみたら、途中で画面に「問題が発生しました。ご不憫をおかけします。この問題をマイクロソフト社に送信してください。ってでちゃって、組んだプログラムのテストみたいなのを出来ないことが多々あるのです。これはいったいどのような事がおこってるのでしょう?Bolrand社のC++って書いてあるコンパイラを使用してます。コンパイルされたからってミスはなかったなんてことはないということでしょうか?? お返事よろしくお願いいたします。

  • FedraCore4でのC言語

    簡単なCのプログラムをテストしようとしたのですが、コンパイラが見つかりません。 パッケージを全部インストールしていない状況でC言語のプログラムををコンパイルするにはどうすればよいのでしょうか?

  • (C,C++言語)関数の引数は自動キャストされる?

    プログラミング言語C,C++の数値計算に関する質問です. 整数データ変数同士のみの計算結果は小数点以下は切り捨てられますよね. もし実数型で計結果を得たいときは,int変数を(double)や(float)でキャストしてあげなければならないことは知っています. ここで,仮引数リストにdouble型変数が設定されている関数の引数にint型変数を与えた時,関数の呼び出し時にキャストしなくても自動でキャストされるのでしょうか. 以下のサンプルコードを作成し,実行してみた結果を次に示します. ---サンプル--- #include <iostream> using namespace std; void printDouble(double val, double val2) { cout << "(double)val = " << val / val2 << endl; } int main(void) { for (int i = 1; i < 5; i++) { cout << i / (i * 2) << endl; printDouble(i,i*2); } } -----実行結果---- 0 (double)val = 0.5 0 (double)val = 0.5 0 (double)val = 0.5 0 (double)val = 0.5 ------------------------- 関数の外での計算は整数に丸められてしまうので i / ( i * 2 ) 計算結果はゼロに,関数の中では与えられた i はdouble型として扱われるので小数点以下の値も残っているということですよね. この場合,printDouble関数へ整数を与えるときには printDouble( (double)i , (double)( i * 2 ) ); といったようにわざわざキャストしなくても自動で仮引数の型でキャストされて関数が呼び出されると理解してもよいのでしょうか. 実行結果から明らかだろ,思われてしまうかもしれませんが,何かの参考書に記述されているのを見たり,人からそう教わったわけではなく,また関数のオーバーロードのこともありますので,質問させて頂きました.よろしくお願いいたします.

  • C言語の勉強にあたって

    今からC言語を勉強していく人から質問されたのですが、勉強にあたって、Cのアプリケーション(コンパイラ等)なしに実際のプログラムの動きを勉強する方法はないでしょうか? これでは漠然とした書き方ですが、例えば、インターネットのHP上でプログラミング→コンパイル→実行をシミュレーションできるようなHPはないでしょうか? こういうHPがあると、とりあえずインターネット環境とC言語の参考書があれば簡単に勉強できると思うんです。 そのようなHP、ありましたら教えてください。 何ヶ所かあるようでしたら、使い方が難しくない(初心者向け)ところが良いです。 よろしくお願いします。

  • C++とCの互換性

    私は今C言語を勉強しているのですが、C言語の参考書にCのコンパイラではなく、C++のコンパイラの使い方が載っていました。これはどういうことなんでしょうか?C++のコンパイラでCもコンパイル出来るということなんでしょうか? ちなみに載っていたコンパイラはMicrosoftのVisualC++です。

専門家に質問してみよう