C/C++プログラミング入門 – C言語の構造体

注意: この記事は1年以上前に掲載されたものです。情報が古い場合がありますのでお気を付け下さい。

久々のC/C++プログラミング入門として、今回は構造体について説明を行いたい。構造体は複数の変数をまとめることができる一種の箱のようなものである。変数が増えるような場合、構造体をうまく使いこなせないと修正の困難なコードになるだろう。

構造体とは

C言語における構造体とは、複数の変数を一つにまとめることができる機能である。例えば、何らかの変数が多数あり、それが一定の法則に従っている場合 ((例えば、データ関係で言えば本の情報やユーザーの情報など)) に構造体としてまとめることによって、すっきりして修正のしやすいコードにすることができる。

構造体自身もint型やfloat型の変数のように定義をして、その変数内の変数に代入したり参照したりして使う形となる。

注意事項

今回はC言語の構造体について説明を行う。C++における構造体は、今回説明する構造体とは違う部分があり ((むしろ後に説明する予定の「クラス」に近いものとなっている)) 、混同は避けるべきである。

構造体サンプルコード

[code lang=”c”]#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct book_info {
int identifier;
char name[100];
char author[100];
char publisher[100];
};

void print_book_information(struct book_info book);

int main() {
// パターン1
struct book_info book1;
book1.identifier = 1;
strncpy(book1.name, "Foo", 100);
strncpy(book1.author, "John Smith", 100);
strncpy(book1.publisher, "Foo Books", 100);
print_book_information(book1);

// パターン2
struct book_info book2 = {2, "Bar", "Jane Smith", "Bar books"};
print_book_information(book2);

return EXIT_SUCCESS;
}

void print_book_information(struct book_info book) {
printf("=====Book information=====\n");
printf("Identifier: %d\n", book.identifier);
printf("Name : %s\n", book.name);
printf("Author : %s\n", book.author);
printf("Publisher : %s\n", book.publisher);
}[/code]

出力

=====Book information=====
Identifier: 1
Name      : Foo
Author    : John Smith
Publisher : Foo Books
=====Book information=====
Identifier: 2
Name      : Bar
Author    : Jane Smith
Publisher : Bar books

解説

今回は本の情報を定義した上でそれを表示する処理を行っている。パターン1とパターン2では書き方が異なるが、やろうとしていることは基本的に同じである。

パターン1

パターン1は、まず構造体を宣言してから、各変数に値や文字列を代入している。

book_info構造体内のidentifierは整数型であるため、そのまま代入できるが、name, author, publisherはchar型の配列であり、厳密には文字列ではないため、以下のような代入は行えない ((そもそもC言語には文字列の概念がなく、char型の配列あるいはポインターなどで代用している)) 。

[code lang=”c”]struct book_info book;
book.name = "Baz"; // エラー。これは行えない[/code]

そのため、通常はstrcpyあるいはstrncpyを使う。BSD系のUnix系システムではstrlcpyも使える。strcpyは文字数の制限をすることができないため、バッファーオーバーランを防ぐことができないため、文字数を制限できるstrncpyあるいはstrlcpyを使うのが望ましい。

パターン2

パターン2では、配列のように初期値を指定する方式を行っている。構造体の上に定義されている変数から順に初期化される。

今回のbook_infoの場合は、「{identifierの値, nameの文字列, authorの文字列, publisherの文字列};」という形になる。

パターン1ではそれぞれの変数の代入を行うことで比較的わかりやすく、構造体内の変数に変更が加わっても影響がほとんどない利点があるが、最適化の状況にもよるが一つずつ代入していくため、わずかながらパフォーマンスが低下する ((今日ではPCの性能が高くなっているため、許容できるレベルである場合がほとんどだが)) 。

パターン2では初期値を指定した上で定義するため、パフォーマンスは高いが、パターン1と比べると比較的わかりづらく、構造体の変数の順番が変わったりした場合に弊害が出る可能性がある。

最後に

今回はC言語の構造体について簡単に説明を行った。C++の構造体はここで説明した内容とは若干異なる部分があるため、基本的にはC言語の構造体がわかればほぼそのまま使えるが、さらなる説明が必要になるため、またの機会にC++特有の機能「クラス」と交えて説明を行いたい。

タイトルとURLをコピーしました