構造体で値をまとめる
商品データC
#include <stdio.h>
typedef struct {
char name[32];
int price;
int stock;
} Product;
int main(void) {
Product apple = {"りんご", 150, 8};
printf("%s: %d円(在庫%d)\n", apple.name, apple.price, apple.stock);
return 0;
}実行結果OUTPUT
りんご: 150円(在庫8)typedefによりstructを毎回書かず、Productという型名で利用できます。
構造体を関数へ渡す
大きな構造体はコピーせず、変更しないポインタとして渡せます。メンバーは->で参照します。
表示関数C
void print_product(const Product *product) {
printf("%s: %d円\n", product->name, product->price);
}前の例のappleへprint_product(&apple)を実行すると「りんご: 150円」と表示されます。
必要なメモリを確保する
mallocは指定したバイト数を確保します。失敗時はNULLを返し、不要になったら必ずfreeします。
入力された個数の配列C
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t count = 3;
int *scores = malloc(count * sizeof *scores);
if (scores == NULL) return 1;
for (size_t i = 0; i < count; i++) scores[i] = (int)(i + 1) * 10;
for (size_t i = 0; i < count; i++) printf("%d ", scores[i]);
printf("\n");
free(scores);
scores = NULL;
return 0;
}実行結果OUTPUT
10 20 30callocとrealloc
callocは要素数と各要素サイズを受け取り、全ビットを0で初期化します。reallocは確保済み領域の大きさを変更します。
配列を拡張C
int *values = calloc(2, sizeof *values);
if (values == NULL) return 1;
int *resized = realloc(values, 4 * sizeof *values);
if (resized == NULL) {
free(values);
return 1;
}
values = resized;
values[2] = 30;
values[3] = 40;
free(values);一時ポインタresizedを使うと、失敗時に元の領域を見失いません。
メモリを安全に扱う
確認すること
- 個数とサイズの乗算がオーバーフローしないか確認する
- 確保結果が
NULLでないか確認する - 確保した領域の範囲内だけを使う
- 所有者を決め、一度だけ
freeする free後のポインタを参照しない
ゼロ初期化の意味
callocの全ビット0が、すべての型で必ず意味上のゼロ値になるとは限りません。ここでは整数配列に利用しています。ミニ課題:商品一覧
商品数に応じてProduct配列を動的確保し、合計在庫金額を計算してください。確保失敗と解放も実装します。
