目的
グローバル変数の使用方法及びその確認
@fujitanozomu さんから色々アドバイスを頂きましたので、このメモを大幅に修正しました。
修正履歴をできるだけキープしたいですがプログラムファイルの差分の表示はできませんでしたので記事だけを差分するようにしました。
ファイル
main.c:グローバル変数numの宣言定義および順番でAとB (AもBも外部関数。外部で変数は確実にグローバルになったかを確認)を処理
(追記)main.h:変数numをexternで宣言。他のcファイルはこのヘッダーをincludeすることで変数numはグローバルになる。
A.h:グローバル変数numを使用することを宣言関数Aは外部で使用されることを宣言
A.c:main.hをincludeしnumを変更して出力(グローバル変数numが変更される)
B.h:グローバル変数numを使用することを宣言関数Bは外部で使用されることを宣言
B.c:main.hをincludeしnumを変更せずに出力(Aで変更されたグローバル変数numを出力)
上記のファイルで、mainで宣言されているnumは、AとBからも使用でき(グローバル変数になるため)、numがAで変更されても、Bからもその変更を確認できることを証明
ファイルの中身
#include"main.h"
#include"A.h" //Aの関数を使用するため
#include"B.h" //Bの関数を使用するため
int num; //変数を宣言
int main(int argc, char *argv[]){
A(); //numを他のファイルで変更させる
B(); //他のファイルで変更されたnumを確認
return 0;
}
extern int num; //他のファイル(ここはmain.c)にnumは定義されているよ、という意味
extern void A(); //A.cで定義されている関数Aは外部で使用されるためにexternで宣言
#include<stdio.h>
#include"A.h"
#include"main.h" //ここでnumはグローバルになる
void A(){
num = 10; //グローバル変数を変更
printf("inside A, num = %d\n", num); //グローバル変数を変更して出力
}
extern void B(); //B.cで定義されている関数Bは外部で使用されるためにexternで宣言
#include<stdio.h>
#include"B.h"
#include"main.h" //ここでnumはグローバルになる
void B(){
printf("inside B, num = %d\n", num); //グローバル変数を変更せずに出力
}
#Aの共有ライブラリを作成
[pirlo@centos8 02]$ gcc -shared -o libA.so -c A.c
#Bの共有ライブラリを作成
[pirlo@centos8 02]$ gcc -shared -o libB.so -c B.c
#メイン処理をコンパイルして実行ファイルを作成
[pirlo@centos8 02]$ gcc -o main main.c -L. -lA -lB
#ファイル一覧
[pirlo@centos8 02]$ ls
A.c A.h B.c B.h libA.so libB.so main main.c main.h
[pirlo@centos8 02]$ ./main
inside A, num = 10 #Aでグローバル変数を変更
inside B, num = 10 #BからAで変更されたグローバル変数を確認
追記
https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
この記事により、関数は変数と違い、コンパイルされる際、コンパイラはexternがあるように処理するためexternを明記しなくても大丈夫のようです。実際にテストしたところ、main.hから#include"A.h"と#include"B.h"を削除しても無事コンパイル・実行できました。