C/C++の型キャストとは正確には何ですか?コンパイラーは、明示的な型キャストが必要(かつ有効)かどうかをどのようにチェックしますか?値に必要なスペースを比較していますか?例えば私が持っている場合:
int a;
double b = 15.0;
a = (int) b;
私が正しく覚えている場合、double値には整数(4バイト)よりも多くのスペース(8バイトでしたか?!)が必要です。そして、両方の内部表現は完全に異なります(2の補数/仮数)。では、内部で何が起こるのでしょうか?ここの例は非常に単純ですが、C/C++には豊富な型キャストがあります。
コンパイラー(またはプログラマー)は、たとえば、 FOO to BAR?
型キャストは、基本的にある型から別の型への変換です。暗黙的(つまり、コンパイラーによって自動的に行われ、おそらくプロセス内の情報が失われる)または明示的(つまり、開発者がコードで指定する)にすることができます。タイプが占めるスペースは、2番目に重要です。より重要なのは、変換の適用可能性(場合によっては便利)です。
暗黙の変換によって情報が失われたり、兆候が失われたり、取得されたり、オーバーフローやアンダーフローが発生したりする可能性があります。コンパイラは、おそらくコンパイル時に生成される警告を除いて、これらのイベントからユーザーを保護しません。スライスは、派生型が暗黙的に基本型に(値によって)変換されるときにも発生します。
まったく危険な変換(たとえば、ベースから派生型への変換)の場合、C++標準では明示的なキャストが必要です。それだけでなく、static_cast
、dynamic_cast
、reinterpret_cast
、const_cast
など、より限定的な明示的キャストを提供します。これらはそれぞれ、明示的キャストを可能な変換のサブセット。キャストエラーの可能性を減らします。
有効な変換(暗黙的および明示的の両方)は最終的にC/C++標準によって定義されますが、C++では、開発者はコンストラクターおよびオーバーロード(キャスト)演算子を使用して、暗黙的および明示的の両方でユーザー定義型の変換を拡張できます。 。
キャストが標準で許可されており、そうでない完全なルールは、非常に複雑になる可能性があります。この回答では、これらのルールのいくつかの簡潔な要約を忠実に提示するように努めました。許可されているものと許可されていないものに本当に関心がある場合は、規格にアクセスし、型変換に関する各セクションを読むことを強くお勧めします。
見落とされがちなことについてお話ししたいと思います。
これは重要です。例えば:
#include <iostream>
void change_one_print_other( int& a, const int& b )
{
a = 0;
std::cout << b << "\n";
}
int main(void)
{
int x = 5, y = 5;
change_one_print_other(x, x);
change_one_print_other(y, static_cast<int>(y));
}
そのキャストは役に立たない。しかし、 見た目はだまされている可能性があります 。
コードの小さなCプログラムを作成し、GCCにアセンブリコードを生成させる方法の指示に従って、コンパイラーは型キャストを行います。
コンパイラが暗黙的に行う方法を知っている特定の型キャストがあります-intへのdoubleはその1つです。小数部分を単に削除します。内部表現はプロセスの一部として変換されるため、割り当ては正しく機能します。
値が大きすぎて正しく変換できないことに注意してください。その場合のルールは覚えていません。コンパイラーの裁量に任される場合があります。