C キャストのソースを表示
新しいページはコチラ
移動:
案内
,
検索
※このページではC言語にも存在していたという意味で記事タイトルが<nowiki>C -キャスト</nowiki>になっていますが、<br /> [[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br /> <br /> == '''キャスト''' == 型変換/型変更/const外しを行うことをキャストと呼びます。const外しは少し特殊な表現ですが、constと同時に定義される型の変更と思えば、型に関する処理という意味では同じです。キャストcastには割り当てるという意味がありますので、新しい型を割り当てる処理と考えれば、それぞれの変換の総称になっていることも納得できるでしょうか。 一般的にキャストは危険な操作です。メモリの使い方を間違えないように型宣言をした変数なのに、それをなかったことのようにしたいというわけですから。もっと緩やかな意味で型を定義したつもりがガチガチすぎるので、変換してコンパイラエラーをかいくぐるという使い方になると思うので、プログラムする人があえて、その危険の潜む変換を指示するという処理になります。大丈夫な変換だとプログラムがお墨付きをだすようなことです。 通常の使い方ですが、危険のおよばない一般的な使い方としては、 unsigned int(文字列の長さとかの用途で符号無しint 正の数のみ) →int(符号付きの整数) のような変換で、unsigned intとして使っているが実際はint型程度の大きさの数字しか扱わない場合には比較的安全な変換と言えます。本当に安全な変換か保障するために、変換する前にunsigned intがintの扱える最大数以下かを確認するのが良いです。確認を事前に行えば情報が欠落することはほぼ無いと言えるでしょう。unsigne intとintを比較すると危険で、int型の負の数と比較した場合は、unsigned intのかなり大きな正の数と一致してしまう可能性があるからです。その逆の変換をする場合でもint型の変数が負の数にないことをたしかめれば、安全な変換が可能です。 と、このような前置きがあればプログラムでは、このキャストは <syntaxhighlight lang="cpp"> char pcComment[] = "test"; int nLimit = 10; unsigned uintLength = 0; uintLength = strlen(pcComment); if(nLimit > (int)uintLength){ … } </syntaxhighlight> のように書くことができて *変換 (int)uintLength if文で使う前に前もってint型の変数に入れているとしたら変換だということが分かりやすいでしょうか? int intLength = (int)uintLength; のように変数の前に "(変換したい型名)変換を必要とする変数名" のような形式でキャストすることができます。このキャストを記述しない場合は、コンパイル時に異なる型を比較しようとしたワーニングが表示されると思います。危ないことをやってるのは、知ってますよ。という意味のキャストになります。サンプルプログラムは短いので、nLimitがint型であるしがらみが語られていませんが、これがどこかのクラスから与えられる数値である箇所を起点としてマイナス3文字目が制限になるパターンがあるような意味になっていたりする場合にstrlenの返却する値がunsigned intなこともあってキャストせざるを得ない状況になるのかもしれません。 int* pintLength のようなポインタ変数があるとしたら 変数の中身を渡さない場合には型の変更として int* pintLength unsigned int* puintLength; puintLength = &uintLength; とされたものを *変更 pintLength = (int*)puintLength; そしてconst付きのint ポインタ変数にnLimitのアドレスを紐づけて、pconstnLimitからは中身を変更できないようにした場合 const int* pconstnLimit; int* pnLimit; pconstnLimit = &nLimit; ※上記のconst付きのポインタはポインタのアドレスは変更できるconstで、アドレスは何度でも入れ替えることができます。アドレスが指し示す中身を変更できないようにするものです。 アドレス自体を変更させないconstにする場合は、int* const pconstnLimit = &nLimit; のように *の後ろにconstを付与します。 const int* const pconstnLimit = …;とすると中身もアドレスも変更できなくなります。値の中身の変更を禁止するcointは 型名の後ろに書くことができますので、 int const * const pconstnLimit = …;とも書けます。どちらにしてもあまり見かけない使い方だとは思います。C++の難しさはこのあたりにあると思う。こうやって書いてもいいという曖昧さ。柔軟さ? *const外し pnLimit = (int*)pconstnLimit; のようにすることができます。キャストは型の大きさに違いがなく、型名が変換できるものや、変更できるものに使いますが、もっと大きなサイズの変数となる構造体やクラスのキャストはキャストできるできないの判定に複雑さが増します。 このような難しい型の変換もあるという背景とキャストに対する仕組みの改善からC++では新しいcastの指定が4つ増えました。 *static_cast 変換 *reinterpret_cast 変更 *const_cast const外し *dynamic_cast 実際に新しさを感じるのはクラスとの関係が深いdynamic_castだけです。上の3つのキャストは先の説明にもあげたCからあったキャストを明示することができるようになって、このキーワードを使って明示的なcastをしようというものです。上記のキーワードを使わないとcastさせないというパターンも存在します。具体的には以下のようになります。 *変換 (int)uintLength '''static_cast<int>'''uintLength *変更 pintLength = (int*)puintLength; pintLength = '''reinterpret_cast<int*>'''puintLength; *const外し pnLimit = (int*)pconstnLimit; pnLimit = '''const_cast<int*>'''pconstnLimit; dynamic_castはクラスの継承関係でcast可能なものと不可能なものがあり、親(基底クラス)から子(派生クラス)へのクラス名変換はキャスト動作はほぼ不可能で、その逆はキャストできるケースがあります。これは親より子の方が肉付けされる分だけ型は大きくなっているはずだからです。その逆の変換であれば、子クラスだけの機能やメンバ変数がそぎ落とされるものの変換が可能になります。このような変換の可否を実行時に判断してくれるのが、dynamic_castです。使い方は上の3つと同じです。クロスキャスト(親子の関係が無いクラス同志のキャスト)やダウンキャスト(そのままは使えない抽象クラスの変数で派生クラスにキャストする親から子をへのキャスト)と呼ばれるキャストも実行時に検索します。 失敗すると例外をスローします。詳しいサンプルはまた後日。まずはクラス関連の記事を全部書いてから、自分もここに戻ってきて記事を書きたいと思います。たぶん、dynamic_castの記事ができるのは、数年後になりそうですね。ごめんなさい。言葉で、ダイナミックキャストのイメージだけでも伝われば幸い。詳しいことは、他のSiteで調べれば、よりイメージが具体化されるでしょう。どういうときに明示しなければエラーになるのか?どういう構造なら変換・変更・const外しができるのか?あいまいなままの説明になっているので、変換・変更・const外しの具体的なサンプルもあったほうがいいでしょうね。
C キャスト
に戻る。
個人用ツール
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ