いつもお世話になっています。
MFCでCプログラミングをしています。
ヘッダファイルの2重定義防止のために、
ヘッダファイル全体を下記のように
囲みました。
<aaa.h>
#ifndef AAA
#define AAA
#define PI 3.141592
void Func();
int wa(int a, int b){
return a+b;
}
#endif
ビルドしたところ、
関数宣言(Func)や#define部分(PI)については、
2重定義が防止されているようなのですが、
関数の実体部分(関数wa)については、
2重定義防止機能が働かず、
***.obj : error LNK2005:
"int __cdecl wa(int a, int b)"
は既に ***.obj で定義されています。
というリンクエラーが表示されます。
関数の種類や
ヘッダファイル内の宣言の順番を
いろいろ変えてみたのですが同じ結果でした。
ここで、このヘッダファイルの先頭に
#pragma onceを使用すると
このリンクエラーは回避されるのですが、
他コンパイラとの互換性の観点から、
#pragma once以外の方法で実現する必要があるので、
困っています。
URLを検索してみたのですが、
このような特殊な場合について記述されているものは
見つけられませんでした。
どなたか解決法又はヒントをご教示頂ければ
ありがたいです。
よろしくお願いします。
No.2ベストアンサー
- 回答日時:
二重インクルードは防止できています。
ただし、あくまで1つのコンパイル単位の中での話です。エラー内容から察すると、2つ以上のソースファイルでaaa.hをインクルードしていますね?コンパイル時点ではエラーにはならずに複数のobjファイルが生成されますが、リンク時にエラーが発生します。これは、リンク実行時に関数waの定義が複数のモジュールで発見されるためです。このようなエラーを防ぐため、通常、ヘッダファイルで関数の定義は行わず、その代わりに
extern int wa(int a, int b);
のように宣言だけを記述します。関数定義はどこかのソースファイルで1回だけ行います。
No.4
- 回答日時:
#2の方の通りかと思います。
aaa.hファイルが問題のヘッダーファイルとして、
ソースファイルがa.c, b.cの2つあるとすると
a.cでは、
#inlucde "aaa.h"
......
b.cでも
#include "aaa.h"
......
とされていると思います。
すると2つのソースから作成されるa.obj,b.objそれぞれに
関数waが定義されており、しかもグローバルなスコープです。
よって、リンク時にwaが2つあるのでエラーになっていると思います。
対処としても、#2の方と同じく
関数waはどこかのソースに実体を記述し、ヘッダーファイルに
関数のプロトタイプを記述するのが通常です。
どうしてもヘッダーファイルに関数の実体を記述したいのでしたら
スコープをstaticにすればエラーを回避できるでしょう
static int wa(int a, int b){
return a+b;
}
でもこれは普通じゃないです。
丁寧な解説を頂き、
エラー原因のメカニズムが良く分かりました。
最終的には、
普通でない方法は辞めることにし、
うまくビルド成功しました。
ご教示ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# 変数のスコープ 5 2023/05/27 17:50
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語初心者です、、、お助けください 2 2023/03/14 20:08
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
このQ&Aを見た人はこんなQ&Aも見ています
-
餃子を食べるとき、何をつけますか?
みんな大好き餃子。 ふと素朴な疑問ですが、餃子には何をつけて食べますか? 王道は醤油とお酢でしょうか。
-
あなたにとってのゴールデンタイムはいつですか?
一週間の中でもっともテンションが上がる「ゴールデンタイム」はいつですか? その逆で、一週間でもっとも落ち込むタイミングでも構いません。 よかったら教えて下さい!
-
「これはヤバかったな」という遅刻エピソード
寝坊だったり、不測の事態だったり、いずれにしても遅刻の思い出はいつ思い出しても冷や汗をかいてしまいますよね。
-
おすすめのモーニング・朝食メニューを教えて!
コメダ珈琲店のモーニング ロイヤルホストのモーニング 牛丼チェーン店の朝食などなど、おいしいモーニング・朝食メニューがたくさんありますよね。
-
とっておきの「まかない飯」を教えて下さい!
飲食店で働く方だけが食べられる、とっておきの「まかない飯」。 働いてらっしゃる方がSNSなどにアップしているのを見ると、表のメニューには出てこない秘密感もあって、「食べたい!!」と毎回思ってしまいます。
-
1 つ以上の複数回定義されているシンボルが見つかりました
C言語・C++・C#
-
【gcc・cygwin】multiple definitionエラーの解決法
C言語・C++・C#
-
2重定義って??
C言語・C++・C#
-
-
4
multiple definitionというエラー
C言語・C++・C#
-
5
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
6
define で 配列
C言語・C++・C#
-
7
C言語のポインタに直接アドレスを割り振りしたい
C言語・C++・C#
-
8
c++,ある関数のクラスから別のクラスの関数を呼ぶ
C言語・C++・C#
-
9
スタティックライブラリ関係のエラーだと思う...
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
2重定義って??
-
visualstudio C# テキストボッ...
-
long型の定数の末尾にLを付ける...
-
関数の実体定義にヘッダファイ...
-
C++ クラスをメンバにもつクラ...
-
C++のfor文について
-
構造体を引数とする、クラス間...
-
C++のコンストラクタを宣言する...
-
inline
-
値を返り値に返すのと参照渡し...
-
C++でboolにintの値を代入する...
-
クラスのメンバ関数を別ファイ...
-
変数の型を定義しなかった場合...
-
64bit → 32bit型へのキャスト
-
waveout関数を使うと「○○は一度...
-
引数で argc argvが使用され...
-
スレッドのスケジューリングポ...
-
main.c:7:43: warning: implici...
-
LNK2019: 未解決の外部シンボル...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
C++のfor文について
-
2重定義って??
-
visualstudio C# テキストボッ...
-
long型の定数の末尾にLを付ける...
-
typedef enumの使い方を教えて...
-
C++でboolにintの値を代入する...
-
プログラムの中で別のmainを呼...
-
構造体の要素すべてに対する四...
-
変数の型を定義しなかった場合...
-
intとINTの違いは?
-
main.c:7:43: warning: implici...
-
【#define】 defineで定義した...
-
構造体の宣言でエラーが出ます。
-
関数の実体定義にヘッダファイ...
-
ハンドルされていない例外が発...
-
void func( void )について
-
エラー「invalid conversion fr...
-
sshdログの意味
-
C言語での方向キー入力判定
おすすめ情報