Code Fix

中級

sizeofが配列の要素数ではなくポインタのサイズを返す

配列に対するsizeofは配列全体のバイト数を返しますが、関数の引数として渡された配列はポインタに変わっているため、同じsizeofが8(ポインタのサイズ)を返してしまいます。

なぜエラーが出ないのか

出力: 2
(エラーなし)
Cは何も報告しません。コンパイルも実行も正常に完了するためです
出力: 2
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  #include <stdio.h>
 2  
 3  int main(void) {
 4      int nums[5] = {1, 2, 3, 4, 5};
 5      int *p = nums;
 6      int count = sizeof(p    ) / sizeof(int);
                             ^
 7      printf("%d\n", count);
 8      return 0;
 9  }
出力: 2期待: 5

pはnumsの先頭要素を指すポインタで、sizeof(p)はポインタ自体のサイズ(8バイト)を返します。配列全体のバイト数が欲しいときは、配列そのものにsizeofを使う必要があります。

直し方: pnums にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  #include <stdio.h>
 2  
 3  int main(void) {
 4      double prices[4] = {9.5, 3.2, 7.1, 4.4};
 5      double *p = prices;
 6      int count = sizeof(p      ) / sizeof(double);
                              ^
 7      printf("%d\n", count);
 8      return 0;
 9  }
出力: 1期待: 4

ポインタ変数のsizeofは指している型によらず常にポインタ自身のサイズです。要素数を得るには配列の変数名に直接sizeofを使います。

直し方: pprices にします。

この問題を解いてみる →

パターン3

 1  #include <stdio.h>
 2  
 3  int main(void) {
 4      char letters[6] = {'a', 'b', 'c', 'd', 'e', 'f'};
 5      char *p = letters;
 6      int count = sizeof(p       ) / sizeof(char);
                               ^
 7      printf("%d\n", count);
 8      return 0;
 9  }
出力: 8期待: 6

char型の配列でも同じ罠があります。ポインタpのsizeofは要素の型と無関係に8(ポインタのサイズ)を返すため、要素数の計算には使えません。

直し方: pletters にします。

この問題を解いてみる →

よくある誤解

配列を関数に渡しても「配列そのもの」が渡されると思いがちですが、Cでは配列は関数の引数になった瞬間に先頭要素へのポインタに変換されます(配列のdecay)。要素数の情報は失われるため、関数内でsizeofから要素数を復元することはできません。

まとめ

sizeofが配列の要素数ではなくポインタのサイズを返すは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)