Project_OKI’s diary

エンジニアの勉強ブログ

C言語基礎知識27(構造体を複数の別ファイルで使用する)

構造体を複数の別ファイルで使用

この記事では、C言語で扱う構造体を、複数のファイル(ソースファイル、ヘッダファイル)で使用する際の使い方について記載する。

 

基本的に、C言語で何かを作成する場合、1つのファイルで終わることは少ない。

複数のソースファイル、ヘッダファイルが作られる場合が多い。

特に組み込みの場合、A.cで代入した値をB.cで参照したい時がある。

今回は、それを構造体でどう行うかについて記載する。

 

1. 目的

 ・構造体を複数のファイル(ソースファイル、ヘッダファイル)で使用する際の使い方について理解する。

 

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

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

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

 

目次

 

2. 構造体を複数ファイルで使用する1

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

  で作成したプログラムを、複数のファイルに分けてみる。

 

 2.1プログラムの作成1(複数ファイルの追加)
//main.cファイル
#include <stdio.h>

#include "main.h"
#include "kannsu.h"


int main(void){
    Square squ;
    
    //値の入力
    squ.storenum    = 10;
    squ.beside      = 10;
    
    //setNum1の実行
    setNum1(squ); 
    //squの値を表示
    printf("storenum = %d\n", squ.storenum);
    printf("beside = %d\n", squ.beside);
    
    //setNum2の実行
    setNum2(&squ); 
    //squの値を表示
    printf("storenum = %d\n", squ.storenum);
    printf("beside = %d\n", squ.beside);
    
    return 0;
}

 

//main.hファイル
#ifndef MAIN_H
#define MAIN_H

//構造体の作成
typedef struct{
    int storenum;
    int beside;
}Square;

#endif
//kannsu.cファイル
//ヘッダのインクルード
#include "kannsu.h"

//関数に構造体を渡して、データを代入
void setNum1(Square squ){
    squ.storenum    = 200;
    squ.beside      = 200;
}

//関数に構造体のポインタを渡して、データを代入
void setNum2(Square *squ){
    squ->storenum   = 500;
    squ->beside     = 500;
}
#ifndef KANNSU_H
#define KANNSU_H

#include "main.h"

//プロトタイプ宣言
void setNum1(Square squ);
void setNum2(Square *squ);
#endif

実行結果:https://paiza.io/projects/nKCqijQyCblJ3SCPLyjEvw?language=c

 基本的に、上記記事の内容を、

 kannsu.cとkansu.hファイルを追加し、分けただけ。


 2.2 プログラムの作成2(複数ファイルでグローバルとして使用する)

・上記プログラムに、Test構造体を追加し、

 Test構造体をグローバルで使用する場合について記載する。

・上記プログラムでは、main関数でローカル変数として宣言し、

 それを、各関数に引数として渡している。

・出来るだけ、ローカルで使用した方が良いが、実際のC言語では、グローバルで使用する場合もある。

 

//main.c
//ヘッダファイルのインクルード
#include <stdio.h>

#include "kannsu.h"
#include "main.h"
#include "hyouzi.h"

//構造体の宣言
//Test test;   //グローバルでの宣言
    
int main(void){
    Square squ;
//    Test test;   //ローカルでの宣言
    
    //初期値の入力
    squ.storenum    = 10;
    squ.beside      = 10;
    test.test1      = 0;
    test.test2      = 0;
    
    setNum1(squ);       //squデータ格納 
    squDisp(squ);       //squデータ表示
    
    setNum2(&squ);       //squデータ格納
    squDisp(squ);       ///squデータ表示
    
    setTest1();         //testデータの格納
    testDisp();          //testデータの表示
    printf("test.test1=%d\n",test.test1);
    
    return 0;
}

 

//main.hファイル
#ifndef MAIN_H
#define MAIN_H

//構造体の作成
//ローカル用構造体
typedef struct{
    int storenum;
    int beside;
}Square;

//グローバル用構造体
typedef struct{
    int test1;
    int test2;
}Test;

//構造体の変数定義
//extern Square squ;    //ローカルで使用:無くてもエラーにならない。
extern Test test;       //グローバルで使用:ないとエラーになる。

#endif
//kannsu.cファイル

#include "kannsu.h"     
#include "main.h"

//構造体の宣言
//Test test;    

//構造体(Square)代入用関数
void setNum1(Square squ){
    squ.storenum    = 200;
    squ.beside      = 200;
}

//構造体に構造体のポインタを渡して計算
void setNum2(Square *squ){
    squ->storenum   = 500;
    squ->beside     = 500;
}

//構造体(Test)代入用関数
void setTest1(){
    test.test1 = 10;
    test.test2 = 20;
}
//kannsu.hファイル

#ifndef KANNSU_H
#define KANNSU_H

#include "main.h"

//プロトタイプ宣言
void setNum1(Square squ);
void setNum2(Square *squ);
void setTest1();

#endif
//hyouzi.cファイル

#include <stdio.h>
#include "hyouzi.h"

//構造体の宣言(グローバル宣言)
Test test;

//squデータを表示する関数
void squDisp(Square squ){
    printf("storenum = %d\n", squ.storenum);
    printf("beside = %d\n", squ.beside);
}

//testデータを表示する関数
void testDisp(){
    printf("test.test1 = %d\n", test.test1);
    printf("test.test2 = %d\n", test.test2);
}
//hyouzi.hファイル
#ifndef HYOUZI_H
#define HYOUZI_H

#include "main.h"

//プロトタイプ宣言
void squDisp(Square squ);
void testDisp();

#endif

実行結果:https://paiza.io/projects/V3AWV3KlaCDVcHINDlyWBA?language=c

 

 2.3 プログラムの説明

 (a) このプログラムは、メイン関数の最初でSquare及びTest構造体の初期化を行い、

  setNum1、setNum2、setTest1で

  構造体のデータを格納している。

  squDisp、testDispで

  構造体に格納されている値をprintfで出力している。

 

 (b) //Test test;   //グローバルでの宣言

  Test構造体は、グローバルとして宣言されている。

  このプログラムでは、main.c、kannsu.cファイルでは、

  コメントアウトされており、hyouzi.cのみでグローバル変数宣言がされている。

 

  グローバルで宣言した場合は、

  hyouzi.cで宣言しても、main.cで宣言しても、kannsuで宣言しても、

  どこでもよい。

  コメントアウトを外して、全てに記載しても問題はない。

  

  逆に言えば、ファイルが多くなるほど、構造体をグローバルで宣言した時、

  意図しない部分で数値が変わってしまったりする可能性があり、管理が難しくなるため、注意が必要。

 

 (c) // Test test; //ローカルでの宣言

  このコメントアウトを外すと、グローバルで宣言されているTest構造体とは別に、

  ローカルでTest構造体が宣言される。

  その場合、メイン関数で出力している printf("test.test1=%d\n",test.test1);

  のtest.test1の値は、グローバルの影響を受けず、0になる。

 

 (d) extern Test test;

  グローバルで複数のファイルで使用する場合、同じ変数ということで、

  extern宣言をする必要がある。

  →extern宣言については下記を参照

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

 

関連記事

過去の記事:

知らないと損するお金の話(ふるさと納税、確定申告とワンストップ納税どっちが得?) - 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言語