ビットとバイト
ビット(bit)はコンピューターの最小単位。1と0を保持・計算できる。
バイト(byte)はコンピューターの最小の処理単位。最初期に広く普及したコンピューターが8ビットコンピューターだったため、8bit=1Byte(噛む)という表現になっている。
詳しくは↓

sizeof演算子
sizeof演算子では、変数や型、配列・構造体等がメモリ上に占めるバイト数を取得可能。
【今日のコード①】
int array[10];
int aaa = sizeof(array);
printf("aのアレイサイズ = %d\n", aaa);
return 0;
【実行結果】
aのアレイサイズ = 40
int型の要素数10の配列…4byte*10 = 40byte
型の変換(キャスト)
C言語では整数同士で計算した場合、結果は整数になる。
このため、余りが出た場合には小数点以下は切り捨てられる。四捨五入もされない。
(例)
3÷2 = 1
コードにすると下記。
【今日のコード②】
int val1, val2, result;
val1 = 3;
val2 = 2;
result = val1 / val2;
printf("%d÷%d=%d", val1, val2, result);
【実行結果】
3÷2=1
上記コードの計算結果の型を「float型」にしても結果は変わらない。
float fres;
fres = val1 / val2;
printf("整数演算(結果をfloat):%d÷%d=%f\n",val1, val2, fres);
【実行結果】
整数演算(結果をfloat):3÷2=1.000000
そこで(int)のように型名を()でくくったものを値や変数の前に書くと、それを指定した型に変換が可能。これを型キャストと呼び、()をキャスト演算子と呼ぶ。
キャスト変換を施した例は下記。
【今日のコード③】
fres = (float)val1 / (float)val2;
printf("整数演算(キャスト):%d÷%d=%f\n", val1, val2, fres);
【実行結果】
整数演算(キャスト):3÷2=1.500000
val1(float)÷val2(float)=1.5(float)となっている。
unsigned int 型に int(符号付)を代入して表示を試みる。
【今日のコード④】
unsigned int val3;
val1 = -10;
val3 = val1;
printf("val1 = %d,val3 = %d\n", val1, val3);
【実行結果】
val1 = -10,val3 = -10
unsigned int に代入したにも関わらず val3 = -10 となっている。
これは
①val1 = 1000 1010 のため、それがそのまま val3 に代入される(符号なしで表現した場合138)。
②%d指定子は「符号付整数」を表示するためのオプションなのでー10がそのまま表示される。
という状況が発生している。
符号なし整数の指定子は%uであり、こちらに置き換えたコードと結果は以下。
【今日のコード⑤】
unsigned int val3;
val1 = -10;
val3 = val1;
printf("val1 = %u,val3 = %d\n", val1, val3);
【結果】
val1 = -10,val3 = 4294967286
-10というのは16進でFFFFFFF6(10進で4294967286)になるので、そのまま表示されている。
※データサイズが大きい型から小さい型への代入は絶対に避けること。
オーバーフロー(桁あふれ)が発生して意図しない値が代入される。
単純な代入では通常、他の変数のメモリを直接上書きすることはないが、
ポインタ操作や配列操作を誤ると、メモリ破壊やクラッシュの原因になる。
ビルド時に警告が出る場合もあるため、明示的な型変換が必要な場合は特に意識してコードを書くこと。
・「通常の変数は一軒家。壊してもその家だけ。」
・「ポインタや配列は長屋。境界を守らないと、隣の家まで壊してしまう(=メモリ破壊)。」
・「だからポインタは便利だけど危険。大人の道具。」
例えば、for文で要素数3の配列(int a[3])を扱うときには下記のようにする必要がある。
for(int i=0, i < 3, i++)
また、ループを逆に回したいときは次の記載
for(int i = 2, i >=0, i–)
a[3]を使わないようにコードを書く必要がある。
※オペランド(被演算子)
演算の対象となる数値や変数・定数などのこと。
(例)
1 × 2 = 2
↑ ↑
これらが「オペランド」。
※NULLアクセス
🌟 NULLアクセスとは?
ポインタが NULL(ヌル)=「どこも指していない」状態のときに、そのポインタを使おうとすること。
これは 重大なエラーを引き起こす(クラッシュ・例外)。
🌟 なぜ起こる?
✅ *ポインタに正しいアドレスがセットされていないのに dereference(p など)した場合
✅ オブジェクトが解放された後のポインタをまだ使っている場合
✅ 未初期化のポインタを使ってしまった場合
🌟 何が起こる?
NULL は「どこにも存在しない特別なアドレス」(通常 0 番地)を意味する。
OS は 0 番地付近へのアクセスを禁止している(不正アクセス)。
→ プログラムはクラッシュする(Segmentation Fault / アクセス違反)。
🌟 たとえ話版(笑)
ポインタ → 手紙の宛先
NULL → 「宛先不明」「封筒が空っぽ」
NULLポインタにアクセスする = 宛先不明なのに配達に行く → 配達員が迷子になって事故る(クラッシュ)
🌟 どう防ぐ?
✅ ポインタを初期化する(NULL / nullptr で初期化してから使う)
✅ 使う前に必ず NULL チェックを行う
✅ delete や free 後はポインタを NULL にする(Dangling pointer 対策)
c
コピーする
編集する
if (p != NULL) {
// 安全に p を使ってよい
}
まとめ一句:
NULLは「何もない」場所。そこに手を伸ばせば、世界が崩れる。
ざっくりこれで OK!
もしもう少し「NULLアクセスが起きやすい典型的な場面」や「実際のエラー例(Segfaultなど)」も知りたければ、追加で出せます。
知っておくと実務でもバグ取りが圧倒的に楽になります✨。
(by ChatGPT)
演算子の優先度
**C言語の演算子の優先順位(Operator Precedence)**を
覚えやすい形で簡潔に整理しておきます ✨。
🌟 基本ルール
✅ 優先順位が高いほど先に評価される
✅ 同じ順位の場合は「結合規則(左→右/右→左)」で順序が決まる
🌟 優先順位表(簡易版)
優先順位 | 演算子例 | 説明 | 結合規則 |
---|---|---|---|
1 | () [] -> . | 関数呼び出し、配列、構造体アクセス | 左→右 |
2 | ! ~ ++ -- + - * & sizeof | 単項演算子(符号反転・インクリメントなど) | 右→左 |
3 | * / % | 乗算、除算、剰余 | 左→右 |
4 | + - | 加算、減算 | 左→右 |
5 | << >> | ビットシフト | 左→右 |
6 | < <= > >= | 比較(大小関係) | 左→右 |
7 | == != | 等価・不等価 | 左→右 |
8 | & | ビットAND | 左→右 |
9 | ^ | ビットXOR | 左→右 |
10 | | | ビットOR | 左⇒右 |
11 | && | 論理AND | 左→右 |
12 | || | 論理OR | 左⇒右 |
13 | ?: | 条件(三項)演算子 | 右→左 |
14 | = += -= *= /= %= <<= >>= &= ^= ` | =` | 代入関連 |
15 | , | コンマ演算子 | 左→右 |
🌟 ポイント解説
✅ 掛け算・割り算は足し算・引き算より優先 → 学校で習う通り
✅ 比較演算子より算術演算子が優先
✅ 論理AND(&&)は論理OR(||)より優先
✅ 代入(=)は最後に評価される → 計算結果が全部終わってから代入
✅ 三項演算子(?:)はクセがある → 優先順位が低めなので注意
まとめ一句:
演算の順は静かなる川の流れ、掛け算先に、代入はあと。
さらに覚え方Tips:
- 関数 → 単項 → 算術 → 比較 → 論理 → 代入 → コンマ
- 特に
&&
→||
→=
の順番だけは必ず意識しておくとバグを防ぎやすい
(by ChatGPT)
(例)
if(a++ > b){}
これを書き直すと
if(a > b)
{ }
a++;
となる。
if(++a > b){}
これを書き直すと
a++;
if(a > b)
となる。前置と後置の場合の処理順序の違いに注意する。
コメント