C言語で関数の引数として構造体のアドレスを渡す方法を解説
構造体の値を受け渡す3つの方法
C言語では、構造体の値をある関数から別の関数へ渡す方法として、主に以下の3つが挙げられます。
- 構造体の各メンバーを個別の引数として渡す
- 構造体全体を引数として渡す
- 構造体のアドレスを引数として渡す
本記事では、3つ目の「構造体のアドレスを引数として関数に渡す方法」について詳しく解説します。
構造体のアドレスを渡す仕組み
構造体のアドレスを引数として渡す場合、処理は以下のような流れで行われます。
- 呼び出し側では、構造体のアドレスを引数として関数に渡します。
- 関数側では、仮引数として「構造体へのポインタ」を宣言し、渡されたアドレスを受け取ります。
関数内では、アロー演算子(->)を使ってポインタが指し示す構造体の各メンバーへアクセスできます。これにより、元の構造体そのものを直接操作することが可能になります。
構造体のアドレスを渡すメリット
- メモリの無駄がない: 構造体のコピーを新たに作成する必要がないため、メモリを節約できます。特に大きな構造体を扱う場合に効果を発揮します。
- 戻り値が不要: 関数はポインタを介して元の構造体全体に間接的にアクセスし、その内容を直接操作できるため、処理結果を戻り値として返す必要がありません。
サンプルプログラム1: 単一の構造体のアドレスを渡す
以下のプログラムは、日付情報を格納する構造体のアドレスを、表示用関数に引数として渡す基本的な例です。
#include<stdio.h>
struct date{
int day;
char month[10];
int year;
};
int main(){
struct date d;
printf("enter the day,month and year:");
scanf("%d%s%d",&d.day,d.month,&d.year);
display(&d);
return 0;
}
void display(struct date *p){
printf("day=%d\n",p->day);
printf("month=%s\n",p->month);
printf("year=%d\n",p->year);
}
main関数ではdisplay(&d)のように構造体変数dのアドレスを渡し、display関数側ではstruct date *pというポインタで受け取っています。各メンバーへのアクセスには、p->dayのようにアロー演算子を使用します。
実行結果
上記のプログラムを実行すると、以下のような結果が得られます。
enter the day, month and year:20 MAR 2021 day=20 month=MAR year=2021
サンプルプログラム2: 構造体配列のアドレスを渡す
次に、複数の学生情報を扱う構造体配列のアドレスを関数に渡す例を紹介します。関数内ではポインタをインクリメント(p++)することで、配列の各要素へ順番にアクセスしています。この方法では構造体のコピーを作成して値を返す必要がないため、メモリの無駄がなく効率的です。
#include<stdio.h>
//構造体の宣言//
struct student{
char Name[100];
int Age;
float Level;
char Grade[50];
char temp;
}s[5];
//関数の宣言//
void show(struct student *p){
//ループ用変数の宣言//
int i;
//出力用のforループ//
for(i=1;i<3;i++){
printf("The Name of student %d is : %s\n",i,p->Name);
printf("The Age of student %d is : %d\n",i,p->Age);
printf("The Level of student %d is : %f\n",i,p->Level);
printf("The Grade of student %d is : %s\n",i,p->Grade);
p++;
}
}
void main(){
//ループ用変数の宣言//
int i;
//構造体へのポインタを宣言//
struct student *p;
//ユーザー入力の読み込み//
for(i=0;i<2;i++){
printf("Enter the Name of student %d : ",i+1);
gets(s[i].Name);
printf("Enter the Age of student %d : ",i+1);
scanf("%d",&s[i].Age);
printf("Enter the Level of student %d :",i+1);
scanf("%f",&s[i].Level);
scanf("%c",&s[i].temp);//バッファのクリア//
printf("Enter the Grade of student %d :",i+1);
gets(s[i].Grade);
}
//ポインタに構造体のアドレスを代入//
p=&s;
//関数の呼び出し//
show(&s);
}
なお、このコードで使用されているgets()関数はバッファオーバーフローの危険性があるため、現在では非推奨とされています。実際の開発ではfgets()などの安全な代替関数を使用することをおすすめします。
実行結果
上記のプログラムを実行すると、以下のような結果が得られます。
Enter the Name of student 1 : Lucky Enter the Age of student 1 : 27 Enter the Level of student 1 :2 Enter the Grade of student 1 :A Enter the Name of student 2 : Pinky Enter the Age of student 2 : 29 Enter the Level of student 2 :1 Enter the Grade of student 2 :B The Name of student 1 is : Lucky The Age of student 1 is : 27 The Level of student 1 is : 2.000000 The Grade of student 1 is : A The Name of student 2 is : Pinky The Age of student 2 is : 29 The Level of student 2 is : 1.000000 The Grade of student 2 is : B
まとめ
構造体のアドレスを関数に渡す方法は、大規模なデータを扱う場合や、関数内で元の構造体の内容を変更したい場合に特に有効な手法です。ポインタとアロー演算子を正しく理解することで、メモリ効率に優れたC言語プログラムを書けるようになります。
-
【Python】TkinterでEnterキーを関数にバインドする方法
キーボードのキーが押されたときに特定の処理を実行することは、ボタン操作と同様にイベントとして扱うことができます。Tkinterアプリケーションでは、bindメソッドを使ってキーイベントをウィジェットやウィンドウに紐付ける(バインドする)ことが可能です。キーイベントが発生すると、あらかじめ登録しておいたハンドラ関数が呼び出され、そのキーに対応した処理が実行されます。bindメソッドの基本構文任意のキーイベントをトリガーしたい場合は、bind(<Key>, ハンドラ) の形式を使用します。特にEnterキーに対応させたい場合は、bind(<Return>, ハンドラ) を使
-
Windows 11でIPアドレスを確認する方法|コマンドプロンプトと設定アプリの手順
インターネット接続に不具合が生じたとき、さまざまな対処法を試す中で、自分のPCのIPアドレスを把握しておくと意外と役立ちます。 IPアドレス(Internet Protocol Address)とは、インターネット上でデバイスを識別するための一意な数値アドレスのことです。機械にとっての「郵便番号」と考えると分かりやすいでしょう。現実世界で郵便番号が住所を特定するように、IPアドレスはコンピューターの場所を示し、デバイス同士がお互いを見つけて通信できるようにしています。 Windows 11でIPアドレスを確認する方法は複数あります。まずは最もシンプルな方法である「コマンドプロンプト」を使う