• ベストアンサー

Cコンパイル時のマルチデファイン優先

Cコンパイル時にincludeファイルの都合上、マルチデファインになってしまいます。 この点はコンパイラが宣言無視をしてくれるのですが、extern優先にしてリンクをするにはどのようにすれば良いのでしょうか。 ファイル内でinclude文(ファイル内)定義より先にextern文でシンボル定義をすれば、extern優先でリンクしてくれるのでしょうか(試して無いのですが)。 コンパラ・リンカ製品の仕様になるのでしょうけれど「マルチデフは絶対ダメ」なコンパイラでない場合、extern宣言を優先にする一般的な方法はありますか 。

noname#34252
noname#34252

質問者が選んだベストアンサー

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.1

extern宣言を優先にしたいけれど、 プログラム中でひとつは実体を定義しないといけないわけですね? (問題を勘違いしてたらすみません) >ファイル内でinclude文(ファイル内)定義より先にextern文でシンボル定義をすれば、 >extern優先でリンクしてくれるのでしょうか。 というよりも、 ヘッダファイルの中には実体定義を書かないのが基本です。 ヘッダファイル内のグローバル変数は (program.h)---- extern int global_x; ------------ だけにしておいて、 どれかひとつの.cファイルで ------------ #include "program.c" int gloval_x; ----------------- のように実体を定義します。 これでリンクすれば実体がひとつに定まります。 プリプロセッサを使った有名な手法があります。 参考URLの『パソコン初心者の館』の 『Cプログラミング診断室』 →第5章 →「ほとんど同じ」 のところに、マクロを使った技が書いてあります。 なお、同じ著者の本『Cプログラミング専門課程』にも 手法が記されています。(第9章「ヘッダーファイル」) いい本なので買っておくといいと思います。 (ヘッダーファイルの多重インクルードを防ぐ手法も書いてます)

参考URL:
http://www.pro.or.jp/~fuji/,http://www.amazon.co.jp/exec/obidos/ASIN/4774100900/
noname#34252
質問者

お礼

御回答ありがとうございます。 使用しているコンパイラなのですが。 メーカ専用機向けの上、アメリカ製->商社->メーカ->商社->サービス。 となっており融通が悪いのです。 メーカは言い訳をしてから説明をするし(なっていない)、include文を変更したくてもメンドウすぎるのです。 つまり、 <<ヘッダファイルの中には実体定義を書かないのが基本です。>> ここから「なってない」提供を受けているため、ややこしいのです。 パソコン上、マイクロソフトCのようにいかない。 そのためいままでは、分割コンパイルをしない利用方法か、外部定義includeファイルを定義作成するしかないという(プログラマーの作成した)プログラムをメンテしているのです。 それを私は無理に分割コンパイルで参照externしているため上記の問題が発生しております。

その他の回答 (1)

  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.2

#1です。 そういう事情でしたか。苦労を知らずに失礼しました。 しかしどうしたらよいかはちょっと思いつきません。 ヘッダーファイルから、extern宣言のみを抜き出して 新しいヘッダーファイルを作ればなんとかなるでしょうが、 もとのヘッダーファイルが複雑すぎるときは現実的でないし…。 (役に立たなくてすみません)

noname#34252
質問者

お礼

当面、面倒ですけど型宣言のマルチ定義で対応できそうです。 作法知らずがメインを作ると厄介の上乗せですね。 御回答ありがとうございました。

関連するQ&A

  • #defineの使い方

    お世話になります。 C#で質問があります。 #defineでシンボルを定義しておいて、 複数の別のファイルから、#ifでコンパイルを切り替えたいのですが、どのようにすれば可能でしょうか? C++の場合は、#includeで出来たと思うのですが・・ よろしくお願いいたします。

  • 分割コンパイルの#defineについて

    分割コンパイルで ファイル1 #include <stdio.h> #define number 10 char string[number]; int main(void){ string[0]='a'; string[1]='b'; file_to(); return 0; } ファイル2 #include <stdio.h> #define number 10 extern char string[number]; void file_to(void){ /***何かの処理をする*****/ } って感じなんですけども、配列string の中身の値をdefineによって指定しているのですが、片方のdefineの値を変更する時、もう一つのdefineも手動で変更しています。関係するファイル数が多くなってくると大変なので、どれかのdefineの値を変化させたら自動的に他のdefineの値も変更するプログラムの組み方はありませんか? 質問がわかりにくいかも知れませんがよろしくお願いします。

  • 分割コンパイルについて

    現在分割コンパイルが分からずに苦戦しています。 下記のリストは構造体を使わなければコンパイラを通すことができましたが、 使うとなぜか通りません。 あれこれ試しましたがどうしても分かりません。 何がおかしいのでしょうか? *define.hで全てのファイルへの定義や宣言を行わせています。 ////////////// //Main.cpp ////////////// #include <stdio.h> #include <conio.h> #include "define.h" int main( void ){ Tmp[0].c = 15; printf("a: %d\n", a); printf("b: %d\n", b); printf("c: %d\n", Tmp[0].c); printf("NUM:%d\n", NUM); aaa(); bbb(); getch(); return 0; } ////////////////// // A.cpp ///////////////// #include <stdio.h> #include "define.h" void aaa( void ){ printf("a: %d\n", a); printf("b: %d\n", b); printf("c: %d\n", Tmp[0].c); printf("NUM:%d\n", NUM); } ////////////////// // B.cpp ///////////////// #include <stdio.h> #include "define.h" void bbb( void ){ printf("a: %d\n", a); printf("b: %d\n", b); printf("c: %d\n", Tmp[0].c); printf("NUM:%d\n", NUM); } ////////////////// // define.cpp ///////////////// #include "define.h" int a = 10; int b = 20; struct Parameter { int c; }; struct Parameter Tmp[NUM]; ////////////////// // define.h ///////////////// #define NUM 100 extern int a; extern int b; extern struct Parameter Tmp[NUM]; void aaa( void ); void bbb( void );

  • defineで定数が置き換えられない?(C言語)

    #defineについて質問です。 #defineは、ソースコード内にこの文字を見つけたら、コンパイルする前にこの文字をこの定数に置き換えて、というプリプロセッサですよね?だから、printfで#defineで定義した定数を出力する場合で、変換指定が必要ない場合は #include <stdio.h> #define DEF 100 void main(){ printf("#defineで定義された定数はDEFです"); } でもいいと思うんです。ですがこのソースコードは間違いで、実行結果は #defineで定義された定数はDEFです(←置き換えられてない) となってしまします。プリプロセッサだけ実行しても、DEFは100に置き換えられずそのままです。printfで#defineで定義した定数を出力させたい場合は書式指定をしなければなりません。なぜ、このような場合は#defineで定義した定数は置き換えられないのでしょうか?回答よろしくお願いします。

  • #defineで置き換えられない

    C言語です。詳しい方、よろしくお願いします。 下記のプログラムをコンパイルして実行したら、画像のようになってしまいます。 コンパイラは、CPad for LSI C-86 ver2.31です。 #include<stdio.h> #define clr() printf("\x1b[2J") void main(void) { while(1){ clr(); printf("test"); } } #defineがどうも置き換えられていないようです。 詳しい方、考えられる原因を教えてください。 よろしくお願いします。

  • CとC++、どちらでコンパイルされているかをソース中で判別する方法

    タイトルのとおり、CとC++のどちらでコンパイルされているのかを、ソース中で判別する方法(#ifなど)を教えて下さい。 目的は、extern "C" という記述がCではエラーになってしまうのですが、CでもC++でもインクルード可能なヘッダファイルにするため、ヘッダファイル中で   #if「C++でコンパイル中」     extern "C" {   #endif としたいのです。 よろしくお願い致します。

  • BORLAND C++5.5 のヘッダーファイルが

    今、ボーランドのコンパイラでC言語の学習をしているのですが、無料のコンパイラを正常にダウンロードして、リンカのファイルも作っているのですが、Cのファイルを作りコマンドプロンプトでコンパイルを実行しても、E2209インクルードファイルStdio.hをオープンできないという表示が出てコンパイルできません。 パスも設定していますし、stdio.hのファイルもしっかりあるのにオープンできないのでどうしていいかわかりません。 どなたか、わかる方が入れば教えていただけないでしょうか?

  • コンパイル時のスイッチについて

    C言語初心者なので申し訳ありませんが,コンパイル時のスイッチについて困っております. 現在, #define tmp ... #ifdef tmp  関数1 #else  関数2 #endif とtmpを定義して切り替えようとしております. 現在コンパイルの切替は,毎回 //#define tmp とコメントアウトして切り替えているのですが, gcc等のコンパイラのコマンドラインから 切り替える方法はあるのでしょうか. 色々調べたら, cc -D tmp みたいな?感じにするのかと思ったのですがうまくいきません. 初歩の質問ですがご教授よろしくお願いします.

  • SolarisとLinuxのグローバル変数の扱いについて

    Solaris用のソースをLinuxで使えるように変更したいのですが、 グローバル変数について以下のようなことが発生していて困っています。 なにか、コンパイルオプションなどで対応はできないものでしょうか? Solaris (CC)では 特にextern宣言しなくても同じシンボルの外部変数はコモンセグメントに1つだけ作成しコンパイル自体は正常である。 しかし、Linux (g++)では externを宣言しないと同じシンボルを再定義したことになりエラーとなる。 これにより、グローバル変数を多用しているプログラムはLinuxでうまくコンパイルができない。 しかし、単純にextern宣言での対応は難しい。 extern宣言は外部で定義してあるグローバル変数を参照する というものだがLinux では 1つの定義を意外は全てexternしなければ、2重定義エラーになってしまう。 つまり、実体が1つであとはそれを参照しているという形でなければいけない。 ところが、その実体をどこにするか特定することができない。 例えば、gというグローバル変数を仮定する。 A.c,B.c,C.cはその3つのソースよりAA.aという静的ライブラリを構成する。 gはA.cで定義してありB.c,C.cはそれを参照する。 ところが C.cは個別にC.oというオブジェクトで他からの呼び出しがあり 別LMにリンクされる。 その時C.c内のgは実体を失うことになり未定義となる。 つまり、どれが実体になるかは何にリンクするかで決まるため 実態を特定できない。 また、共通のヘッダにグローバル変数が定義されている場合も、重複するというエラーを起こすため、 共通ヘッダからグローバル変数を分離し、何れかのソースにグローバル変数の実態を定義させる必要がある。 共通ヘッダを使っている他のソースはそのグローバル変数の実態を参照するようにexternの宣言をする。

  • define で 配列

    #defineで配列を定義したいのですがこのようなことは可能でしょうか? ヘッダファイル(test.h)で #define MAX (2) int A[MAX]={20,30}; ソースファイルで #include <stdio.h> #include "test.h" int main(){ int i; for(i=0;i<MAX;i++){ printf("A[%d]=%d\n",i,A[i]); } return 0; } とやれば出来るのですが、このヘッダファイルを複数のソースで参照すると 多重定義であるとおこられてしまいます。 #defineで #define A[MAX] {20,30} のように配列を定義する方法は存在するのでしょうか? どなたか良い方法を御存じの方、ご教授お願いします。

専門家に質問してみよう