C/C++における初期化されていないプリミティブ型変数の値は?
はじめに
CやC++を学び始めた人がよく抱く疑問の一つに、「初期化していないプリミティブ型の変数には、いったいどんな値が入っているのか?」というものがあります。
結論から言うと、その値はシステムやコンパイラによって異なります。「コンパイラが自動的に0を代入してくれる」と想定しがちですが、実際はそうとは限りません。整数型なら0、浮動小数点型なら0.0になる場合もありますが、文字型の場合はどうなるのでしょうか。
検証用サンプルコード
以下のコードは、char型、float型、int型、double型、long型の変数を宣言しただけで初期化せずに、それぞれの値を出力する例です。
#include <iostream>
using namespace std;
main() {
char a;
float b;
int c;
double d;
long e;
cout << a << "\n";
cout << b << "\n";
cout << c << "\n";
cout << d << "\n";
cout << e << "\n";
}実行結果(Windows系コンパイラの場合)
1.4013e-045 0 2.91499e-322 0
実行結果(Linux系コンパイラの場合)
0 0 0 0
このように、同じコードでも環境によって出力結果が変わることが分かります。Windows系のコンパイラでは、スタック上に残っていたゴミ(不定値)が出力されることがあり、Linux系のコンパイラではたまたま0に近い値になったケースです。つまり、これらの値は保証されたものではないという点が重要です。
なぜデフォルト値が代入されないのか?
「では、なぜCやC++は変数に自動的に初期値を設定しないのか?」という疑問が生じます。
その答えは、スタック上の変数を初期化する処理はオーバーヘッドが大きく、実行速度に悪影響を与えるためです。C/C++は性能を最優先とする言語であり、不要な初期化コストを避ける設計になっています。そのため、ローカル変数には以前の処理で使われたメモリの残骸(不定な中間値)がそのまま残っていることがあります。
まとめ:必ず明示的に初期化しよう
このような理由から、C/C++ではプリミティブ型の変数を使用する前に、必ず自分で初期化することが鉄則です。未初期化の変数を読み取ることは、C++では未定義動作(Undefined Behavior)とされており、予測不能なバグやセキュリティ上の脆弱性の原因にもなります。
安全なコードを書くためにも、変数宣言時の初期化を習慣づけましょう。例えば int c = 0; のように宣言と同時に値を代入するか、可能であればC++11以降の波括弧初期化 int c{0}; を活用すると安心です。
-
C/C++で学ぶAA木(AA Tree)とは?基本概念と平衡化操作を徹底解説
AA木(AA Tree)とはコンピュータサイエンスにおいて、AA木(AA Tree)とは、順序付きデータを効率的に格納・検索するために実装された平衡木(バランスドツリー)の一種です。AA木は、赤黒木(Red-Black Tree)の変種として扱われます。赤黒木は二分探索木の一形態であり、要素の追加や削除を効率的にサポートします。赤黒木と大きく異なる点は、AA木では赤いノードを右の子としてのみ追加でき、左の子としては配置できないという制約があることです。この制約により、2-3-4木ではなく2-3木をシミュレートすることになり、その結果、木の保守操作が大幅に簡素化されます。赤黒木の平衡化アルゴリズ
-
C/C++における引数の型強制(Argument Coercion)とは?仕組みとサンプルコードで解説
本記事では、C言語およびC++における「引数の型強制(Argument Coercion)」について解説します。引数の型強制とは、関数に渡された引数の型を、コンパイラがある型から別の型へ自動的に(暗黙的に)変換する仕組みのことです。この変換は「引数の昇格ルール(argument promotion rule)」に従って行われます。つまり、より小さいデータ型の引数は、より大きいデータ型へと変換されますが、その逆の変換は行われません。なぜなら、大きなデータ型から小さなデータ型へ変換すると、データの一部が失われる(桁あふれや精度の低下が発生する)恐れがあるためです。暗黙的な型変換がどのように行われる