Project_OKI’s diary

エンジニアの勉強ブログ

C言語基礎知識28(構造体の中で構造体を宣言する)

構造体の中で構造体を宣言する

この記事では、C言語で扱う構造体の中で構造体を宣言した場合の使い方について記載する。

例えば、構造体Aがあり、それを構造体Bの中でAを宣言する場合などがある。

そうした場合の使い方について記載する。

 

1. 目的

 ・構造体の中で構造体を使う場合の振る舞いについて知る。

 

構造体については下記にも記載している:

C言語基礎知識7(構造体1) - Project_OKI’s diary

C言語基礎知識17(構造体とポインタとアロー演算子の使い方) - Project_OKI’s diary

 

目次

 

2. 構造体の中で構造体を宣言した場合の使い方

 2.1プログラムの作成
#include <stdio.h>

//TTest構造体の作成
typedef struct{
    int test1;
    int test2;
}TTest;

//TSamp構造体の作成
typedef struct{
    TTest samp1;    //構造体TTestで宣言
    TTest samp2;    //構造体TTestで宣言
    int   samp3;
}TSamp;

//プロトタイプ宣言
void funcA(TSamp *gsamp);

int main(void){
    // Your code here!
    //TSamp構造体の宣言
    TSamp gsamp;

    //関数 funcAの実行
    //引数として、TSamp構造体のポインタを渡す。
    funcA(&gsamp);
    
    //構造体の中を出力
    printf("test1=%d\n",gsamp.samp1.test1);
    printf("test2=%d\n",gsamp.samp1.test2);
    printf("samp3=%d\n",gsamp.samp3);
}

///TSampの中のsamp1に値を代入する関数
void funcA(TSamp *gsamp){
    //ポインタで宣言しなおす。
    //TTest をptestポインタとして宣言
    TTest *ptest;
    //ptestを、引数のgsampのsamp1をとする。
    ptest = (TTest *)&gsamp->samp1;
    //ptest -> test1など、ポインタ指定で、代入。
    ptest -> test1 = 4;
    
    //gsampポインタのまま使用する。
    gsamp -> samp1.test2 = 2;     ///ポインタを使って構造体に格納
    gsamp -> samp3 = 1;
}

実行結果:https://paiza.io/projects/qyXd9-TpsuKrthKVpJGxYg?language=c


 2.2 プログラムの説明

  (a) このプログラムでは、TSamp構造体の中で、

   TTest構造体をtestとして宣言している。

   基本的な使い方は変わらない。

   まず、TSmap構造体を宣言して、

   その中のTTest構造体で宣言された変数を使う場合、

   TSamp構造体変数 . TTest構造体変数 . 変数

   で使用する。

 

  (b) TSamp gsamp;

   メイン関数で、TSamp構造体をgsampとして宣言している。

 

  (c) printf("test1=%d\n",gsamp.samp1.test1);

   gsampのsamp1のtest1にアクセスし、その値を出力している。

   ・gsampがTSamp構造体変数

   ・samp1がTTest構造体変数

   ・test1がTTest構造体で用意されている変数。(int型)

   値は、funcA関数で入れている。

 

  (d) void funcA(TSamp *gsamp)

   構造体gsampをポインタとして引数に渡している。

   ポインタとして渡す意味については下記を参照

   →C言語基礎知識17(構造体とポインタとアロー演算子の使い方) - Project_OKI’s diary

 

  (e) TTest *ptest;

    ptest = (TTest *)&gsamp->samp1;

   通常、書く場合は、gsamp -> samp1.test2 = 2;

   で、gsampのsamp1のtest2にアクセスできる。

   しかし、sampの構造体の中の変数が多い場合、省略したくなる時がある。

 

   そんな時に使えるのが、TTest 構造体をポインタとして宣言し、

   ptestをgsamp->samp1として指定する。

 

   これにより、ptest -> test1 というように、

   gsamp -> samp1.test1というように書くところを、

   省略することが出来る。

 

   以下に、ポインタを使った場合と、使わない場合の

   メリット、デメリットについて記載する。

 

  ポインターを介してアクセスする場合 直接メンバーにアクセスする場合
メリット  

・動的なデータ構造を扱う場合、ポインタを介してアクセスする必要がある

・コードが簡潔で、可読性が高い
 

・構造体の複数のメンバーにアクセスする場合、コードが簡潔になる

・単一のメンバーにアクセスする場合、直接アクセスする方が使いやすい場合がある
デメリット    ポインターの型を考慮する必要がある。コードが複雑になる場合がある ・動的なデータ構造を扱う場合、ポインタを介してアクセスする方が扱いやすい
  ポインターがNULLである場合には、クラッシュする可能性がある ・構造体の複数のメンバーにアクセスする場合、コードが長くなる場合がある

 

 

関連記事

過去の記事:

知らないと損するお金の話(ふるさと納税、確定申告とワンストップ納税どっちが得?) - Project_OKI’s diary

C言語基礎知識6(関数) - Project_OKI’s diary

C言語基礎知識7(構造体1) - Project_OKI’s diary

C言語基礎知識8(enum:列挙型) - Project_OKI’s diary

C言語基礎知識9(typedef) - Project_OKI’s diary

C言語基礎知識10(extern宣言) - Project_OKI’s diary

C言語基礎知識11(#define) - Project_OKI’s diary

 

組み込みC言語