[c言語] さっと復習(14) 構造体

構造体(こうぞうたい、: structure)はプログラミング言語におけるデータ型の一つで、1つもしくは複数の値をまとめて格納できる型。それぞれのメンバー(フィールド)は型が異なっていてもよい点が配列と異なる。

フリー百科事典『ウィキペディア(Wikipedia)』

構造体とは複数の変数を一つにまとめたもの。

例えば、ある人間を表すものとして、名前や年齢、性別・・・といった無数の要素が考えられる。

構造体を使うことで、これらを人間の構成要素としてまとめることができる。

構造体のそれぞれの変数を、構造体のメンバという。

#include <stdio.h>
#include <string.h>

struct member {
    int id;
    char name[256];
    int age;
};

int main(void) {
    struct member data;
    
    data.id = 1;
    strcpy(data.name, "Mike");
    data.age = 12;

    printf("ID:%d Name:%s Age:%d\n", data.id, data.name, data.age);

    return 0;
}

構造体を配列として扱う。

C言語のtypedefについて

#include <stdio.h>
#include <string.h>

struct member {
    int id;
    char name[256];
    int age;
};

typedef struct member member_data;

int main(void) {
    int i;
    member_data data[] = { 
        {1, "Mike", 12},
        {2, "John", 13},
        {3, "Taro", 14}
    };
    
    for (i=0; i<3; i++) {
        printf("ID:%d Name:%s Age:%d\n", data[i].id, data[i].name, data[i].age);
    }

    return 0;
}

ポインタで構造体を扱う。

C言語のアロー演算子(->)を分かりやすく、そして深く解説

#include <stdio.h>
#include <string.h>

// struct member {
//     int id;
//     char name[256];
//     int age;
// };
// typedef struct member member_data;

// 以下の表記で上と同じ処理。
typedef struct {
    int id;
    char name[256];
    int age;
 } member_data;

void set_data(member_data*, int, char*, int);
void show_data(member_data*);

int main(void) {
    member_data data[4];
    int id[] = {1, 2, 3};
    char name[][256] = {
        "Mike",
        "John",
        "Taro"
    };
    int age[] = {12, 13, 14};
    int i;

    for (i=0; i<3; i++) {
        set_data(&data[i], id[i], name[i], age[i]);
    }

    for (i=0; i<3; i++) {
        show_data(&data[i]);
    }

    return 0;
}

void set_data(member_data* data, int id, char* name, int age) {
    data->id = id;
    strcpy(data->name, name);
    data->age = age;
}

void show_data(member_data* data) {
    printf("ID:%d Name:%s Age:%d\n", data->id, data->name, data->age);
}

構造体と参照渡し

大量のデータを扱う可能性のある構造体では、メモリ容量の理由で、値渡しではなく、参照渡しを使った方が良い場合が多い。

  • 参照渡しでは、スタック領域が圧迫されない。
  • 参照渡しでは、データのコピーが起こらない。
#include <stdio.h>

typedef struct {
    int id;
    double num;
} sample_data;

// 値渡し
void func_call_by_val(sample_data);
// 参照渡し
void func_call_by_ref(sample_data*);

int main(void) {
    sample_data s1 = {1, 1.23};
    sample_data s2 = {1, 2.34};

    printf("ADDRESS_s1:%p\nADDRESS_s2:%p\n", &s1, &s2);

    func_call_by_val(s1);
    func_call_by_ref(&s2);

    printf("s1.id:%d s1.num:%lf\n", s1.id, s1.num);
    printf("s2.id:%d s2.num:%lf\n", s2.id, s2.num);

    return 0;
}

void func_call_by_val(sample_data data) {
    puts("--start call by val");
    printf("id:%d num:%lf\n", data.id, data.num);
    printf("ADDRESS:%p\n", &data);

    data.id = 5;
    data.num = 6.78;
    puts("--end call by val");
}

void func_call_by_ref(sample_data* pdata) {
    puts("--start call by ref");
    printf("id:%d num:%lf\n", pdata->id, pdata->num);
    printf("ADDRESS:%p\n", pdata);

    pdata->id = 5;
    pdata->num = 6.78;
    puts("--end call by ref");
}