ユーニックス総合研究所

  • home
  • archives
  • c-struct-arg

C言語で構造体を引数に渡す方法

  • 作成日: 2022-01-05
  • 更新日: 2024-03-19
  • カテゴリ: C言語

C言語の構造体を引数に渡す方法

C言語では構造体を扱うことができます。
この記事では構造体を関数の引数に渡す方法を具体的に解説します。

構造体は関数とともによく使われます。
そのため関数における構造体の扱い方を押さえておくのは有用と言えます。
今回は↓を中心に解説します。

  • 構造体を引数にコピーして渡す
  • 構造体のポインタを引数に渡す
  • 構造体の配列を引数に渡す

C言語や他の言語を扱うYoutubeも公開しています。
興味がある方は以下のリンクからご覧ください。

Youtubeの当チャンネル

関連記事

目が覚めるC言語のdo-while文の使い方【ループ処理、初心者向け】
明快!C言語のcontinue文の使い方
君はまだC言語のdefineのすべてを知らない【マクロ、プリプロセス】
メッセージボックスの型と構造体 - Rustで作るWindowsアプリ
プログラミングのポインタをわかりやすく解説【C言語】

関連動画
C言語の構造体を関数の引数に渡す方法 - YouTube

構造体を引数にコピーして渡す

↓のような関数の定義があったとき、この関数の引数に構造体を渡すと構造体がコピーされます。

void func(struct Animal arg) {  
    ...  
}  

具体的には↓のようなコードになります。

#include <stdio.h>  

// 動物を表す構造体  
struct Animal {  
    int age;  // 年齢  
    char name[40];  // 名前  
};  

// 引数のargには構造体がコピーされる  
void func(struct Animal arg) {  
    // argのメンバを出力  
    printf("age[%d] name[%s]\n", arg.age, arg.name);  
}  

int main(void) {  
    // cat変数を定義する  
    struct Animal cat = { 20, "Tama" };  

    // funcにcatをコピーして渡す(値渡し)  
    func(cat);  

    return 0;  
}  

上記のコードをコンパイルして実行すると↓のような結果になります。

age[20] name[Tama]  

上記のコードではmain関数内でstruct Animal構造体の変数catを定義しています。
そしてそのcatfunc()に渡しています。

    // cat変数を定義する  
    struct Animal cat = { 20, "Tama" };  

    // funcにcatをコピーして渡す(値渡し)  
    func(cat);  

この時、関数の呼び出し側の引数を実引数、関数の定義側の引数を仮引数と言います。
実引数catfunc()の仮引数argにコピーされて渡されます。

// 引数のargには構造体がコピーされる  
void func(struct Animal arg) {  
    // argのメンバを出力  
    printf("age[%d] name[%s]\n", arg.age, arg.name);  
}  

引数argにはcatのデータがコピーされていますので、catargはそれぞれ別のメモリ上に確保されています。
そのためmain()関数側でcatのデータを変更したり、func()側でargのデータを変更しても、catargそれぞれは干渉しません。

このような値渡しによる引数への構造体の渡し方は、一般的にあまり効率がよくありません
というのも、構造体のメンバが増えればそれだけコピーのコストが増えるからです。
そのため、速度を必要とするプログラムでは後述するポインタ渡し(アドレス渡し)のほうが一般的です。

関連記事
C言語の構造体をコピーする

構造体のポインタを引数に渡す

構造体のポインタを関数の引数に渡すには↓のようにします。

#include <stdio.h>  

// 動物を表す構造体  
struct Animal {  
    int age;  // 年齢  
    char name[40];  // 名前  
};  

// 引数のargには構造体のポインタが渡される  
void func(struct Animal *arg) {  
    // argのメンバを出力  
    printf("age[%d] name[%s]\n", arg->age, arg->name);  
}  

int main(void) {  
    // cat変数を定義する  
    struct Animal cat = { 20, "Tama" };  

    // funcにcatのアドレス(ポインタ)を渡す  
    func(&cat);  

    return 0;  
}  

func()関数の引数は「struct Animal *arg」です。
これはstruct Animalのポインタ変数(ポインタ引数)になります。

// 引数のargには構造体のポインタが渡される  
void func(struct Animal *arg) {  
    // argのメンバを出力  
    printf("age[%d] name[%s]\n", arg->age, arg->name);  
}  

main()関数側では構造体変数のcatのアドレス(ポインタ)をfunc()に渡しています。

    // cat変数を定義する  
    struct Animal cat = { 20, "Tama" };  

    // funcにcatのアドレス(ポインタ)を渡す  
    func(&cat);  

変数の頭に&(アンパサンド)を付けるとその変数のアドレスを取り出すことができます。

このような「struct Animal *arg」という引数は関数内で構造体のデータを間接的に参照したい&変更したい場合などによく使われます。
constを付けていないのでargで参照できるデータはfunc()内でも変更が可能です。

void func(struct Animal *arg) {  
    arg->age = 30;  
    strcpy(arg->name, "Hige");  
}  

参照だけしてデータを変更する予定がない場合は引数にconstを付けて「const struct Animal *arg」のように書きます。

// constを付けたポインタ  
void func(const struct Animal *arg) {  
    // 書き込みできないのでエラーになる  
    arg->age = 30;  
}  

関連記事
C言語の構造体のポインタの使い方

構造体の配列を引数に渡す

構造体の配列も関数の引数に渡せます。

#include <stdio.h>  

// 動物を表す構造体  
struct Animal {  
    int age;  // 年齢  
    char name[40];  // 名前  
};  

// 配列を引数に取る  
void func(struct Animal animals[]) {  
    // animalsを出力  
    printf("0: age[%d] name[%s]\n", animals[0].age, animals[0].name);  
    printf("1: age[%d] name[%s]\n", animals[1].age, animals[1].name);  
    printf("2: age[%d] name[%s]\n", animals[2].age, animals[2].name);  
}  

int main(void) {  
    // 配列を定義する   
    struct Animal cats[] = {  
        { 20, "Tama" },  
        { 30, "Pochi" },  
        { 40, "Yamada" },  
    };  

    // funcに配列を渡す  
    func(cats);  

    return 0;  
}  

func()関数の引数は「struct Animal animals[]」になってます。
これは一見すると配列のように見えますが、実体はただのポインタです。
ですので配列を引数に渡す場合は関数側の引数を「struct Animal *animals」にしても大丈夫です。
見た目的には[]にしたほうが配列だとわかるので、配列の場合は*ではなくて[]が使われることが多くあります。

関連記事
C言語の構造体の配列の使い方

おわりに

今回はC言語の構造体を関数の引数に渡す方法を解説しました。
構造体は関数とセットでよく使われます。

🦝 < 構造体を引数にシュート

🐭 < C言語マスターに俺はなる