質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

7722閲覧

インクルードガードをしているつもりですが、グローバル変数の多重定義によるエラーが出ます

abustoy

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/08/07 10:33

プリプロセス指令#ifndef #endifを使いグローバル変数の宣言を一度だけにしたつもりなのですが、グローバル変数の多重定義によるエラーが出ます。どこが間違っているのでしょうか。
ソースコードは3つのファイルに分かれていますmain.cとhead.cとhead.hです。

発生している問題・エラーメッセージ

multiple definition of `GLOBAL'

該当のソースコード

c

1以下main.cです 2 3#include <stdio.h> 4#include "head.h" 5int main(void) 6{ 7 printf("%d\n",GLOBAL); 8 printf(HOGE); 9 10 return 0; 11} 12 13以下head.cです 14 15# include "head.h" 16 17以下head.hです 18 19#ifndef HOGE 20#define HOGE "hoge" 21int GLOBAL=3; 22#endif

試したこと

1.gcc -c main.c head.c
によりオブジェクトファイルmain.oとhead.oを作成しました。
2.gcc -o main main.o head.o
によりmain.oとhead.oをリンクさせて実行可能ファイルmain.exeを作成しようとしました。しかし 「multiple definition of `GLOBAL'」とエラーが出てしまいました。

プリプロセス指令#ifndef #endifを使いグローバル変数GLOBALの宣言を一度だけにしたつもりなのですが、どこが間違っているのでしょうか教えていただけないでしょうか。

補足情報(FW/ツールのバージョンなど)

コンパイラはgccです。cygwinでコマンドを記述しております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ヘッダに書く関数プロトタイプは純粋に宣言だけなので、複数のソースコードに差し込まれて何ら問題ないのですが、int GLOBAL=3;定義ですので、複数のソースコードに差し込むと「同じ変数が複数回定義される」ことになって、リンクが正常に行えません

(「複数のソースコードに登場する」ことが問題なので、「同じヘッダが1つのソースコードで複数回読まれるのを防ぐ」インクルードガードは無関係です)。

対応策としては、「ヘッダにはextern int GLOBAL;と宣言だけ書いて、どこか1つのソースコードでint GLOBAL=3;と定義する」というのが正攻法です。

投稿2021/08/07 10:41

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abustoy

2021/08/07 10:58

ご回答ありがとうございます。head.hをmain.cの時とhead.cの時の2回インクルードしているので、2回目のインクルードの時にはオブジェクト形式マクロHOGEが定義されているからhead.hはコードの中身が空になっていて、グローバル変数GLOBALが二回目は定義されないと考えていました。しかし、この二回目という概念自体間違っておりますよね?
guest

0

ベストアンサー

head.hには、GLOBALというデータの「定義」が書かれています。
main.cとhead.cではそれぞれhead.hをインクルードしていますから、
main.cとhead.cの両方でそれぞれにGLOBALというデータを定義していることになります。
データを定義しているということは、データの実体を持っているということです。
GLOBALというデータの実体をそれぞれに持っているmain.oとhead.oをリンクしたら、GLOBALが2つになってしまうのでエラーとなります。
データの「定義」(definition)と「宣言」(declaration)は別です。
そのあたりを掘り下げて学んでみてください。

投稿2021/08/07 10:42

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abustoy

2021/08/07 10:50

ご回答ありがとうございます。お聞きしたいのは、head.hをmain.cの時とhead.cの時の2回インクルードしているので、2回目のインクルードの時にはオブジェクト形式マクロHOGEが定義されているからhead.hはコードの中身が空になっていて、グローバル変数GLOBALが二回目は定義されないと考えました。この考え方の間違いを教えていただきたいです。
itagagaki

2021/08/07 10:58

main.cコンパイル時にはmain.cにhead.hがインクルードされます。 head.cコンパイル時にはhead.cにhead.hがインクルードされます。 この2つのコンパイルはまったく互いに独立していますから、いずれにおいてもマクロHOGEは未定義です。
abustoy

2021/08/07 11:01

すみません、その通りですね。main.cとhead.cでのhead.hのインクルードに順番があるものだと勘違いしておりました。迅速な回答とても助かりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問