【2026年8月最新】C言語sizeof演算子の使い方完全ガイド|配列・構造体・ポインタでハマる罠と対策
この記事の内容
「配列の要素数を取ろうとsizeofを使ったのに、関数の中に入れた瞬間に値がおかしくなる」——C言語を書いたことがある人なら、一度はこの罠にハマった経験があるのではないでしょうか。
sizeof演算子は、C言語の中でも最も基本的でありながら、最も誤解されやすい機能のひとつです。配列の要素数を取得する、構造体のメモリサイズを調べる、ポインタのサイズを確認する——用途はシンプルなのに、「配列がポインタに変わる」「構造体のサイズが単純な合計と一致しない」といったC言語特有の仕様が絡むと、途端に挙動が読めなくなります。
この記事では、sizeof演算子の基本的な使い方から、配列・構造体・ポインタそれぞれで起こりがちな罠、実務でのバグパターンと防止策までを、正確な技術情報にもとづいて整理します。さらに後半では、こうした細かい仕様を人間がすべて暗記していなくても、AIが正確なコードを書いてくれる時代になったことが、非エンジニアの経営者にとって何を意味するのかもあわせて解説します。
この記事を最後まで読むと、次の7つが明確になります。
01 BASICS sizeof演算子とは何か(基礎知識) C言語で最初に習うのに、最後まで正確に理解されにくい演算子
sizeofは関数ではなく演算子です。カッコを付けてsizeof(int)のように書くことが多いため関数だと誤解されがちですが、実際には+や*と同じ「単項演算子」の一種です。型名に対して使う場合はカッコが必須ですが、変数や式に対して使う場合はカッコを省略できます(sizeof x;のような書き方も文法上は可能です)。
📚 用語解説
sizeof演算子:型や変数、式が占めるメモリのサイズを「バイト単位」で返すC言語の単項演算子。戻り値の型は符号なし整数型のsize_t。関数のように見えるが、実体はコンパイラが処理する演算子であり、多くの場合コンパイル時に結果が確定する。
sizeofが返す値の型はsize_tという符号なし整数型です。size_tの実際のビット幅は処理系(コンパイラ・OS・CPUアーキテクチャ)によって異なり、32bit環境では32bit、64bit環境では64bitになるのが一般的です。printfでsize_t型の値を出力する際は、書式指定子として%zuを使うのが標準的な作法です。
📚 用語解説
size_t:sizeofや配列の添字など「負の値を取らないサイズ・個数」を表すために使われる符号なし整数型。実際の幅は処理系依存(32bit環境なら4バイト、64bit環境なら8バイトが一般的)。負の数と比較・演算すると符号なし整数への暗黙変換で意図しない挙動になりやすいため注意が必要。
1-1. コンパイル時に評価されるという性質
sizeofの大きな特徴は、多くの場合コンパイル時に評価される点です。つまり、プログラムを実行する前に、コンパイラが型情報から結果を計算して確定させます。これは実行時にコストがかからないという意味で、パフォーマンス上のメリットでもあります。
ただし例外があります。C99以降で導入された可変長配列(VLA: Variable Length Array)に対してsizeofを使う場合は、配列のサイズが実行時にならないと分からないため、実行時に評価されることになります。「sizeofは必ずコンパイル時に決まる」と断定してしまうと、このVLAのケースで誤りになる点は覚えておく必要があります。
sizeofが返す具体的な数値(intが4バイトかどうか、構造体が何バイトになるか等)は、コンパイラ・OS・CPUアーキテクチャによって変わり得る「実装依存」の値です。「必ずこうなる」という断定的な情報を見かけたら、まず手元の環境で実際にsizeof(...)を出力して確認する習慣をつけると事故を防げます。
#include <stdio.h>
int main(void) {
printf("sizeof(char) = %zu\n", sizeof(char));
printf("sizeof(int) = %zu\n", sizeof(int));
printf("sizeof(double)= %zu\n", sizeof(double));
return 0;
}
/* 出力例(多くの一般的な環境):
sizeof(char) = 1
sizeof(int) = 4
sizeof(double)= 8
※ 実際の値は処理系によって異なり得る */
02 ARRAYS 配列とsizeof:要素数の計算方法 sizeofを使った定番の要素数取得テクニックと、その落とし穴
配列に対してsizeofを使うと、配列全体が占めるバイト数が返されます。これは「要素数 × 1要素あたりのサイズ」で計算された値です。この性質を利用すると、次のような式で配列の要素数を求めることができます。
要素数 = sizeof(配列全体) ÷ sizeof(配列の先頭要素)
例:int arr[10]; size_t n = sizeof(arr) / sizeof(arr[0]);
#include <stdio.h>
int main(void) {
int arr[10];
size_t total_bytes = sizeof(arr); /* 配列全体のバイト数 */
size_t element_bytes = sizeof(arr[0]); /* 1要素分のバイト数 */
size_t element_count = total_bytes / element_bytes;
printf("total_bytes = %zu\n", total_bytes);
printf("element_bytes = %zu\n", element_bytes);
printf("element_count = %zu\n", element_count); /* 10 になる */
return 0;
}
📚 用語解説
配列(の要素数):C言語の配列は「同じ型のデータが連続してメモリに並んだもの」。sizeof(配列)は配列全体のバイト数を返すため、1要素あたりのバイト数で割ることで要素数を逆算できる。ただしこの計算は、配列そのものの実体が見えているスコープでのみ正しく動く。
2-1. なぜこの計算式が成立するのか
配列は同じ型の値がメモリ上に連続して並んだデータ構造です。したがって「配列全体のバイト数」は「1要素のバイト数 × 要素数」に必ず一致します。sizeofはコンパイル時に配列の型情報(要素の型と個数)を把握しているため、この計算が正確に行えます。
この方法は配列そのものが宣言されているスコープで使う限り、非常に信頼性の高いテクニックです。ループ処理の上限を決めるときなど、C言語では定番のイディオムとして広く使われています。
この計算式は、あくまで「配列の実体(int arr[10]のような宣言)」に対してのみ正しく動きます。ポインタ変数に対して同じ計算をすると、まったく異なる(多くの場合誤った)結果になります。次の章で扱う「関数に配列を渡したとき」がその典型例です。
2-2. 多次元配列でのsizeof
多次元配列でもsizeofの考え方は同じです。int matrix[3][4];のような2次元配列であれば、sizeof(matrix)は「3×4×sizeof(int)」に相当するバイト数を返します。行数を知りたければsizeof(matrix) / sizeof(matrix[0])、列数を知りたければsizeof(matrix[0]) / sizeof(matrix[0][0])という形で、次元ごとに分解して計算していくのが基本の考え方です。
03 STRUCTS 構造体とsizeof:アライメント・パディングの罠 構造体のサイズが「メンバーの単純合計」と一致しないことがある理由
構造体(struct)に対してsizeofを使うと、そのメンバー全体を格納するのに必要なバイト数が返されます。ここで多くの人がつまずくのが、「メンバーのsizeofを単純に足し算した値」と、構造体全体のsizeofが一致しないことがあるという点です。
📚 用語解説
構造体(struct):異なる型の変数(メンバー)を1つにまとめて扱うためのC言語のデータ型。例えば「名前・年齢・スコア」のように異なる種類の情報をひとまとまりのデータとして表現したいときに使う。構造体全体のサイズはsizeof(構造体名)で取得できる。
3-1. アライメント(メモリ整列)とパディングとは
多くのCPUアーキテクチャでは、特定の型のデータを「その型のサイズの倍数となるメモリアドレス」に配置したほうが、読み書きの効率が良くなる(場合によっては、整列していないアクセスがエラーになる環境すらある)という性質があります。この「型ごとに決められた配置ルール」のことをアライメント(メモリ整列)と呼びます。
コンパイラは、構造体のメンバーをこのアライメントのルールに沿って配置しようとします。その結果、メンバーとメンバーの間に「使われない隙間」が挿入されることがあります。この隙間のことをパディングと呼びます。パディングが入ると、構造体全体のサイズは各メンバーのsizeofを単純に足し合わせた値より大きくなることがあります。
📚 用語解説
アライメント/パディング:アライメントは「型ごとに定められたメモリ配置の整列ルール」。パディングは、そのアライメントを満たすためにコンパイラがメンバー間や構造体末尾に挿入する「使われない詰め物のバイト」。この仕組みにより、構造体全体のサイズは各メンバーのサイズの単純合計と一致しないことがある。
たとえば「1バイトのchar」の直後に「4バイトのint」を並べた構造体を考えると、intを4バイト境界に配置するために、char直後に数バイトのパディングが挿入されるケースがあります。ただし具体的に何バイトのパディングが入るかは、コンパイラ・ターゲットCPU・最適化設定によって変わる実装依存の挙動であり、「必ずこうなる」と断定できるものではありません。気になる場合は、手元の環境で実際にsizeof(構造体名)を出力して確認するのが確実です。
構造体のサイズやメンバーのオフセット(構造体内での位置)は環境依存です。ファイル保存やネットワーク通信で構造体をそのままバイト列として送受信する設計は、送信側と受信側でコンパイラやCPUアーキテクチャが異なると壊れるリスクがあります。外部とデータをやり取りする場合は、決め打ちせずシリアライズ処理を明示的に書くのが安全です。
3-2. パディングを抑える方法とそのトレードオフ
コンパイラによっては#pragma packや、GCC/Clangの__attribute__((packed))といった拡張機能で、パディングを詰めて構造体を小さくすることができます。ただしこれらは標準C言語の機能ではなくコンパイラ拡張であり、移植性が下がったり、整列されていないメモリアクセスによる速度低下・一部環境でのエラーを招いたりする可能性があります。安易に使う前に、本当にサイズ最小化が必要な場面かどうかを見極める必要があります。
構造体のメンバーを「サイズの大きい型から小さい型の順」に並べ替えると、パディングが減ってサイズが小さくなることがあります。これはコンパイラ拡張に頼らず、標準的な書き方だけでメモリ効率を改善できる実践的なテクニックです。
04 FUNCTION ARGS 関数に配列を渡すときの罠(ポインタへのdecay) C言語で最も有名な初心者の落とし穴のひとつ
ここがsizeofに関する最も有名な罠です。C言語では、配列を関数の引数として渡すと、その配列は「配列の先頭要素を指すポインタ」に変換(decay)されます。関数の内部では、受け取った引数はもう「配列」ではなく「ポインタ」として扱われるため、その中でsizeofを使うと、配列全体のサイズではなく、ポインタ自体のサイズが返ってきます。
#include <stdio.h>
void check_size(int arr[]) {
/* ここでの arr は実際にはポインタ (int*) として扱われる */
printf("関数内: sizeof(arr) = %zu\n", sizeof(arr));
}
int main(void) {
int numbers[10];
printf("呼び出し元: sizeof(numbers) = %zu\n", sizeof(numbers));
check_size(numbers);
return 0;
}
/* 出力例(64bit環境の場合):
呼び出し元: sizeof(numbers) = 40 (10要素 × 4バイト)
関数内: sizeof(arr) = 8 (ポインタ自体のサイズ)
※ 具体的な数値は環境により異なるが、
「呼び出し元と関数内で値が変わる」という現象自体は
C言語の仕様として一貫して発生する */
📚 用語解説
ポインタ:メモリ上のアドレス(場所)を値として持つ変数。「配列の先頭要素を指すポインタ」を経由することで、配列の中身に間接的にアクセスできる。関数に配列を渡すと、その配列は自動的に先頭要素へのポインタに変換される(配列のポインタへのdecay)。
4-1. なぜこの仕様になっているのか
C言語の設計上、配列を関数の引数として値渡しでまるごとコピーする仕組みは用意されていません。その代わりに、配列名を渡すと自動的に先頭要素へのポインタへと変換される、という規則が採用されています。これは効率面での合理的な設計判断ではありますが、結果として「配列のつもりで渡した引数が、関数の中ではポインタになっている」という初心者にとって直感に反する挙動を生みます。
この仕様を知らずに「関数の引数でsizeofを使えば元の配列サイズが取れるはず」と思い込んでコードを書くと、意図しないバイト数(多くの場合4バイトや8バイトといったポインタ自体のサイズ)が返ってきて、後続の処理がすべて狂ってしまいます。
4-2. 正しい対処法
この問題を回避する最も確実な方法は、要素数を別の引数として明示的に渡すことです。C言語の標準ライブラリ関数(例:qsortやmemcpy)も、配列本体とは別に要素数やバイト数を引数として受け取る設計になっているのは、この仕様上の制約に対応するためです。
一部のコンパイラは、配列引数に対してsizeofを使っているコードに警告を出すことがあります(例: GCCの-Wsizeof-array-argオプションなど、警告の有無・種類はコンパイラやバージョンにより異なります)。警告が出た場合は「気のせい」で済ませず、要素数を渡す設計に直す判断材料にしてください。
05 POINTERS & TIMING ポインタのサイズと評価タイミング 「何を指しているか」に関係なく一定であること、評価タイミングの原則と例外
ポインタ自体のsizeofは、そのポインタが何の型を指しているかに関係なく、同じ処理系であれば一定です。これは、ポインタが「値そのもの」ではなく「メモリアドレス」を保持する変数だからです。int型を指すポインタも、double型を指すポインタも、構造体を指すポインタも、同じ処理系であれば同じバイト数になるのが一般的です(32bit環境なら4バイト、64bit環境なら8バイトが多いですが、これも実装依存です)。
#include <stdio.h>
int main(void) {
int *p_int = NULL;
double *p_double = NULL;
char *p_char = NULL;
printf("sizeof(p_int) = %zu\n", sizeof(p_int));
printf("sizeof(p_double) = %zu\n", sizeof(p_double));
printf("sizeof(p_char) = %zu\n", sizeof(p_char));
/* 多くの64bit環境ではいずれも 8 になる(指す型に関係なく同じ) */
return 0;
}
5-1. sizeofの評価タイミング:原則と例外
前半の章でも触れたとおり、sizeofは原則としてコンパイル時に評価されます。式の中身(例えば関数呼び出しを含む式)を実際に実行するわけではなく、その式が持つ「型」だけを見て、必要なバイト数を計算します。そのため、sizeof(some_function())のように書いても、some_function()自体は呼び出されず、戻り値の型のサイズだけが計算される、という点は覚えておくとよい性質です。
ただし、C99以降で導入された可変長配列(VLA)に対するsizeofだけは例外です。VLAは配列のサイズが実行時に決まる変数(関数の実行中に決まるサイズを使って宣言する配列)であるため、そのsizeofも実行時に評価される必要があります。「sizeofは常にコンパイル時に決まる」という説明を見かけたら、このVLAの例外があることも合わせて押さえておくと、より正確な理解になります。
📚 用語解説
コンパイル時評価 / VLA(可変長配列):コンパイル時評価とは、プログラムの実行前(コンパイルの段階)で計算結果が確定すること。sizeofは通常この性質を持つが、C99以降の可変長配列(VLA、宣言時に変数でサイズを指定する配列)に対しては、サイズが実行時にしか分からないため、sizeofも実行時に評価される例外的なケースとなる。
sizeofの
対象を確認
固定サイズの
型・配列か?
コンパイル時に
サイズが確定
実行時まで
サイズが未確定
06 COMMON BUGS 実務でありがちなバグパターンと防止策 sizeofまわりで発生しやすい典型的なミスをチェックリスト化
ここまで見てきた仕様を踏まえて、実務のコードレビューで実際によく指摘される、sizeofまわりの典型的なバグパターンを整理します。
| バグパターン | 起こること | 防止策 |
|---|---|---|
| 配列を関数に渡した後、内部でsizeofを使う | ポインタのサイズが返り、要素数の計算が狂う | 要素数を別引数として渡す |
| sizeof(ポインタ)を要素サイズと勘違いしてmallocに使う | 確保するメモリ量が意図と異なり、バッファオーバーフローの原因になり得る | sizeof(*ptr)やsizeof(要素の型)を使う |
| 構造体をそのままファイル/通信で送受信する | 環境が変わるとパディングの違いでレイアウトが崩れる | 明示的なシリアライズ処理を書く |
| strcpy等の文字列処理でsizeof(char配列)と文字列長を混同する | 終端のヌル文字やマルチバイト文字の扱いを誤る | strlenと役割を区別して使い分ける |
6-1. sizeofと文字列長(strlen)の違い
char型の配列に対するsizeofは「配列として確保されているバイト数」を返しますが、strlen関数は「文字列の実際の長さ(終端のヌル文字\0を含まない、実際に使われている文字数)」を返します。この2つは似て非なる値であり、配列の確保サイズと、実際に入っている文字列の長さが常に一致するとは限りません。
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[100] = "hello";
printf("sizeof(buf) = %zu\n", sizeof(buf)); /* 100 (確保している配列のサイズ) */
printf("strlen(buf) = %zu\n", strlen(buf)); /* 5 (実際の文字列の長さ) */
return 0;
}
strlenが返すのは「バイト数」であり「文字数」ではありません。UTF-8など1文字が複数バイトで構成されるマルチバイト文字を扱う場合、strlenの戻り値は見た目の文字数と一致しないことがあります。文字数そのものを数えたい場合は、文字コードを意識した専用の処理やライブラリを使う必要があります。
6-2. 静的解析・コンパイラ警告を活用する
sizeofまわりのバグの多くは、目視のコードレビューだけでは見落とされがちです。コンパイラの警告オプションを厳しめに設定する、あるいは静的解析ツールを併用することで、こうした「動くけれど危険なコード」を検出しやすくなります。人間の集中力に依存しない仕組みを用意しておくことが、実務では特に重要です。
07 GENAI CASE STUDY 【独自データ】GENAI社内のAIコード品質チェック実運用 Max 20xプラン契約会社が、開発現場でAIをどう使っているか
ここでは、弊社(株式会社GENAI)で実際にAIエージェント「Claude Code」を運用している状況を、数値と事例ベースで公開します。今回のテーマであるsizeofのような「細部の仕様」がからむコードレビューの現場で、AIがどう機能しているかをリアルに知っていただくための章です。
| 項目 | 内容 |
|---|---|
| 契約プラン | Claude Max 20x(月$200 / 約30,000円) |
| 利用開始 | 2025年後半〜 |
| 利用部署 | 経営・営業・広告・開発・経理・秘書業務まで全社 |
| 開発領域での主な用途 | WordPress/LP制作・スクリプトの書き捨て・コードレビュー支援 |
弊社では「全ての業務を何かしらClaude Codeに絡ませる」という方針で運用しており、開発領域も例外ではありません。細かい仕様の見落とし(今回のようなsizeofの罠を含む)は、人間のレビューだけに頼るとどうしても抜け漏れが出やすい領域ですが、AIエージェントに一次チェックを任せることで、体感として開発業務における書き捨てスクリプトやツール開発のたびに数時間単位の確認作業が削減されています。
上記は弊社の肌感ベースの数値であり、業種・業態・担当者のスキルによって削減時間は変動します。「完全自動化」や「バグがゼロになった」という意味ではなく、あくまで人間のレビュー負荷を軽減する参考情報としてご覧ください。
7-1. 弊社全体の業務削減データ(参考)
開発領域に限らず、弊社では複数の業務領域でClaude Codeを活用しています。以下は2026年4月時点の肌感ベースの概算値です。
| 業務領域 | 主な用途 | 概算削減時間 |
|---|---|---|
| 営業 | 提案書・見積・顧客別資料の自動生成 | 週20時間 → 週2時間 |
| 広告運用 | 週次レポート・CPA分析・配信内容調整 | 週10時間 → 週1時間 |
| ブログ記事 | SEO記事執筆・リライト・内部リンク最適化 | 1本8時間 → 1本1時間 |
| 経理 | 請求書チェック・経費仕訳・Freee連携 | 月40時間 → 月5時間 |
| 秘書業務 | 日報生成・議事録・スケジュール調整 | 日2時間 → 日15分 |
| 開発 | WordPress/LP制作、スクリプト書き捨て | 都度数時間削減 |
08 BEYOND MEMORIZATION 【独自】仕様の細部を暗記しなくていい時代の経営インパクト sizeofのような低レベルな知識は、経営者にとって何を意味するのか
ここまで読んで「配列がポインタに変わる」「構造体のサイズが単純な合計と一致しない」といった話に、正直ピンとこなかった経営者の方も多いと思います。それは自然なことです。sizeofの仕様は、C言語を専門に扱うエンジニアであっても、油断すると踏み外す繊細な領域だからです。
ただし、ここで考えていただきたいのは「この知識を誰が正確に扱えるか」という問題自体が、この数年で構造的に変わってきているということです。かつては、こうした細部の仕様を正確に把握している人材(経験豊富なCエンジニア)を採用するか、社内で長期間かけて育成するかしか選択肢がありませんでした。
8-1. 「知らないと事故る」から「AIが正確に書いてくれる」へ
現在のClaude Codeのような自律型AIエージェントは、今回取り上げたsizeofの配列decayや構造体のアライメントといった、人間のエンジニアでも間違えやすい仕様を踏まえたコードを、高い精度で生成・レビューできます。もちろん「絶対にミスをしない」と保証されているわけではなく、重要な箇所は人間によるレビューが必要ですが、少なくとも「この仕様を知っている人材を採用・育成できるまで開発を進められない」という制約からは解放されつつあります。
これは経営者にとって、実は非常に大きな意味を持ちます。「専門的なC言語エンジニアを採用・育成しなくても、業務システムの自動化や改修に着手できる」ということだからです。これまで「エンジニアがいないから」という理由で止まっていた社内の業務システム改善が、AIエージェントを介することで動き出す可能性があります。
8-2. 非エンジニアがこの変化を活かすための3ステップ
とはいえ、いきなり「全部AIに任せよう」と考えると失敗しがちです。弊社の導入支援の経験からは、以下のようなステップで着手するのが現実的だと考えています。
面倒な業務を
1つだけ選ぶ
Claude Codeに
任せてみる
効果を検証し
横展開する
弊社(株式会社GENAI)自身も、専任のC言語エンジニアを何人も抱えているわけではありません。それでも、業務で必要になるスクリプトやツールの書き捨て、社内システムの細かい改修を、Claude Codeを介して回せています。「技術者を採用・育成しなくても、業務システムを自動化できる」という時代の変化を、実際に社内で体感している立場から、この記事をお届けしています。
09 CONCLUSION まとめ sizeofの正確な理解と、そこから見える経営への示唆
この記事では、C言語のsizeof演算子について、基本的な使い方から、配列・構造体・ポインタそれぞれで起こりやすい罠、実務でのバグパターンと防止策、そして弊社GENAIの実運用データと、こうした知識を経営者が暗記しなくてよくなった時代の意味までを整理しました。最後にポイントを振り返ります。
最も重要なメッセージをお伝えします。sizeofのような細部の仕様を、経営者自身がすべて暗記する必要はありません。大事なのは「こうした細部の正確性が、システムの品質やバグの有無を左右する」という感覚を持ったうえで、それをAIエージェントに任せるという判断ができることです。
弊社では、Claude Codeを「開発の細部を正確にこなしてくれるパートナー」として位置づけることで、専任のエンジニアを大量に抱えなくても、業務システムの改修や自動化を前に進めています。この考え方に共感いただけた方は、ぜひ以下のAI鬼管理までお気軽にご相談ください。
「技術者を採用・育成しなくても自動化できる」を、AI鬼管理が一緒に設計します
sizeofのような細部の仕様に振り回されず、業務システムの自動化を前に進めたい方へ。
弊社の実運用ノウハウをベースに、個別に導入設計のご相談を承ります。
NEXT STEP
この記事の内容を、あなたのビジネスで
実践してみませんか?
AI活用を自社で回せるようになりたい方へ
AI鬼管理
Claude Code・Cowork導入支援から業務設計・社内浸透まで実践ベースで伴走。「自社で回せる組織」を90日で作る経営者向けトレーニング。
よくある質問
Q. sizeof(配列)とsizeof(ポインタ)の違いは何ですか?
A. sizeof(配列)は配列全体のバイト数(要素数×1要素のサイズ)を返しますが、sizeof(ポインタ)はポインタ自体が占めるサイズ(多くの環境で4バイトまたは8バイト)を返します。配列を関数に渡すと配列はポインタにdecayするため、関数の内部でsizeofを使うとポインタのサイズが返ってしまう点が典型的な混同ポイントです。
Q. なぜ関数に配列を渡すとsizeofで正しい要素数が取れなくなるのですか?
A. C言語の仕様上、配列を関数の引数として渡すと、その配列は自動的に「先頭要素へのポインタ」に変換(decay)されます。関数の内部では受け取った引数はもう配列ではなくポインタとして扱われるため、sizeofを使うとポインタ自体のサイズが返り、元の配列サイズは失われます。対処法として、要素数を別の引数として明示的に渡す設計が広く使われています。
Q. 構造体のサイズがメンバーの合計と一致しないのはなぜですか?
A. CPUが特定の型のデータを効率よく読み書きするために、型ごとに決められたメモリ整列ルール(アライメント)があり、これを満たすためにコンパイラがメンバーの間や構造体の末尾に「パディング」と呼ばれる詰め物のバイトを挿入することがあるためです。具体的な挿入量はコンパイラやCPUアーキテクチャによって異なる実装依存の挙動です。
Q. sizeofは実行時に計算されるのですか、それともコンパイル時ですか?
A. 基本的にはコンパイル時に評価され、実行時のコストはかかりません。ただし例外として、C99以降で導入された可変長配列(VLA)に対してsizeofを使う場合は、配列サイズが実行時にしか決まらないため、実行時に評価されます。「常にコンパイル時」と断定せず、この例外も押さえておくと正確です。
Q. アライメントやパディングを気にしないといけないのはどんな場面ですか?
A. 構造体をそのままファイルに保存したり、ネットワーク経由で送受信したりする場面で特に注意が必要です。送信側と受信側でコンパイラやCPUアーキテクチャが異なると、パディングの入り方が変わって構造体のレイアウトが一致せず、データが正しく読めなくなる可能性があります。こうした用途では、明示的なシリアライズ処理を書くのが安全です。
Q. sizeof(arr)/sizeof(arr[0])で要素数を求める方法はいつ使えなくなりますか?
A. この計算式は、配列そのものの実体が見えているスコープでのみ正しく機能します。配列を関数に引数として渡した場合、関数の内部ではその引数はポインタとして扱われるため、この式を使うと誤った結果になります。配列の実体があるスコープ(多くは呼び出し元)で要素数を計算し、必要であれば別の引数として関数に渡す設計が推奨されます。
Q. 非エンジニアの経営者がこうした技術的な仕様を理解する必要はありますか?
A. 細部を暗記する必要はありません。ただし「配列とポインタは別物」「構造体のサイズは単純合計にならないことがある」といった、細かい仕様の正確性がシステムの品質を左右するという感覚を持っておくことは、開発を依頼したりAIの提案を評価したりする際の判断材料として役立ちます。
Q. Claude CodeはC言語のような低レベルなコードも正確に書けますか?
A. 今回取り上げたsizeofの配列decayや構造体のアライメントのような、人間のエンジニアでも間違えやすい仕様を踏まえたコードを高い精度で生成・レビューできます。ただし絶対にミスをしないと保証されるものではないため、重要な箇所は人間によるレビューを組み合わせる運用が現実的です。
Claude Codeで業務自動化を90日で叩き込む
経営者向けの伴走型パーソナルトレーニング
AI鬼管理へのお問い合わせ
この記事を読んで気になった方へ。
AI鬼管理の専門スタッフが、御社に最適な
業務自動化プランを無料でご提案します。




