
以下のようなプログラムを組んでいます。
//main.h
static int hoge;
void someOperation();
//hoge.cpp
#include "main.h"
extern int hoge;
void someOperation()
{
hoge = 15;
}
//main.cpp
#include <stdio.h>
#include "main.h"
extern int hoge;
int main()
{
someOperation();
printf("%d\n",hoge);
return 0;
}
このプログラムを実行したのですが、自分の予想した15という出力ではなく、不定値になるようなのです。
自分の予想では、someOperationで操作するhogeも、main内で操作するhogeも同じになるようにと思いexternをつけているのですが、なにがまずいのでしょうか?
ご存知の方、ご教授お願いします。

No.1ベストアンサー
- 回答日時:
結論から言えば、
static int hoge;
で、static をつけてはいけません。
この場合、hoge.cpp と main.cpp のどちらか一方に、
int hoge;
他方に、
extern int hoge;
が必要になります。
これを一括管理するテクニックとしては、以下のようなものが紹介されていました。
main.h
#if defined(GLOBAL_HERE)
#define EXT
#define DEF(x) = (x)
#else
#define EXT extern
#define DEF(x)
#endif
EXT int hoge;
main.cpp
#define GLOBAL_HERE
// この後で、inlude すると、EXT 指定した変数は、実態が宣言される
#include "main.h"
hoge.cpp
// こちらでは(ほかのファイルでも) GLOBAL_HERE は定義しない
#include "main.h"
// こちらでは、EXT 指定した変数は、 extern と読み替えられる
初期化が必要なときには、
EXT int hog DEF(10);
などとすると、
#define GLOBAL_HERE
のあとで include された場合は、
int hoge = (10);
そうでない場合には、
extern int hoge;
となります。
No.2
- 回答日時:
★まずいですね。
・まず main.h のヘッダファイルに static int hoge という変数の実体があります。
結論から言うとこのような記述は避けるべきなのです。
理由は
・hoge.cpp で main.h をインクルードしていますが、ここで hoge.cpp でしか使えない
static int hoge が実体として作られます。これに 15 を代入していますが、static キーワードが
付いているので他のソースファイル(main.cpp)からアクセスできません。見えないので。
・また main.cpp でも main.h をインクルードしていますが、こんどは main.cpp 用でしか使えない
static int hoge が実体として作られます。つまり2つの hoge 変数が存在します。
・main.cpp では、この自分で見える hoge=0 が表示されます。
決して hoge.cpp の hoge 変数ではありません。注意。
// hoge.cpp
static int hoge=15; ←main.cpp からは参照できない(隠されている)
// main.cpp
static int hoge=0; ←main.cpp ではこれを表示している
※hoge がそれぞれのソースファイルに1つずつ作られて合計2つあります。
解決策:
・main.h ヘッダには extern int hoge; のプロトタイプ宣言だけをします。
そして hoge.cpp に extern int hoge=0; と定義します。
そして someOperation() 関数内で hoge=15; とします。
・main.cpp では main.h をインクルードしますので『extern int hoge;』の
記述は必要ありません。→あっても問題はありませんけど。
//main.h
extern int hoge;
void someOperation();
//hoge.cpp
#include "main.h"
extern int hoge = 0; ←※かならず何かの値を代入すること
void someOperation()
{
hoge = 15;
}
//main.cpp
#include <stdio.h>
#include "main.h"
int main( void )
{
someOperation();
printf( "%d\n", hoge );
return 0;
}
以上。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が解説!あなたの声を行政に届ける「パブリックコメント」制度のすべて
社会に対する意見や不満、疑問。それを発信する場所は、SNSやブログ、そしてニュースサイトのコメント欄など多岐にわたる。教えて!gooでも「ヤフコメ民について」というタイトルのトピックがあり、この投稿の通り、...
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バイナリファイルから文字列を...
-
【Jquery】changeイベント毎にa...
-
Linux バイナリ実行できない "...
-
2次元のJSON形式の配列の展開
-
【正規表現】【javascript】CR...
-
ASP+アクセスでのSQLコメントに...
-
別のSubで宣言されている変数を...
-
C#OpenCv V4にのエラーに関する...
-
innerHTML実行後のイベント
-
[初心者]javascriptのfor文でな...
-
配列の格納
-
javascriptを用いて作成された...
-
gas スプレッドシートがアクテ...
-
初回アクセスから●時間経過後、...
-
Perlの配列をJavaScriptに渡せ...
-
Latexに関する質問です。
-
XMLHttpRequestでキャッシュを...
-
javascriptで2つのArrayの...
-
引数が分かりません。
-
JavaScriptで平日のみをカウン...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ボタンをクリックすると数が増...
-
【正規表現】【javascript】CR...
-
同じ型【ハイフンと数字】だけ...
-
ASP+アクセスでのSQLコメントに...
-
サブウインドウから親ウインド...
-
HTTPSのとき":"が"%3A"ではなく...
-
confirmの連続?
-
VC++のちらつき防止方法
-
Boolean型配列中のTrueの有無を...
-
Vb.netのグローバル変数の宣言...
-
javascriptで文字挿入でtoggle...
-
コールバック関数(?)をループし...
-
【Jquery】changeイベント毎にa...
-
ifreamをリロードしたい
-
Excel VBA の ChangeFileAccess
-
MFCのキャプション変更
-
Linux バイナリ実行できない "...
-
-(ハイフン)_(アンダーバー)の...
-
2次元のJSON形式の配列の展開
-
C# .NET DataGridView の行を追...
おすすめ情報