• 締切済み

C言語のexternとアドレス渡しについて

組み込み系です。 c言語でソフトを作っています。 初心者です。 例えば、Aさんがmain.cファイルにあるmain関数を作成し、 Bさんがsub.cファイルにあるsub関数を作成するとします。 mainで取得した複数のデータをsubに渡し、subが加工演算して、mainに返すとします。 複数のデータを渡す場合、引数でポインタ渡しが考えられます。 または、subがexternで外部参照する方法があります。 (複数データはグローバルでstaticを付けてないとします) 正直どちらのやり方が望ましいのでしょうか? お互いメリットデメリットがあるのでしょうか? 私の考えでは、externの場合、その複数データの名前が変わるとコンパイルエラーになる それぐらいしか思いつきません。 よろしくお願いします。

noname#220914
noname#220914

みんなの回答

  • catpow
  • ベストアンサー率24% (620/2527)
回答No.3

>>ここで疑問なのが2案の存在価値です。 2案使うなら3案で良いじゃんと思います。 C言語に限りませんが、関数の独立性というか、「複合設計」でいうモジュール間の依存関係が低い設計が望ましいですね。 そして、その視点でみたとき、2案のほうが、3案よりも依存する変数の数は同じだとしても、依存するものが引数関連だと分かるため、プログラマからみたとき、依存度が分かりやすくなると思います。 また、いろんなモジュール間でまとまったデータを持ちまわりするってことも多いと思います。 そういう場合でも、2案のほうが良いと思います。 つまりは、「暗黙の依存関係」が「明白な依存関係」になるってことです。 ちなみに、かなり昔、米国からデータベースっぽい機能のあるC言語のソースを会社の金で購入して、いろいろといじったのですが、そのときに巨大なCソース群では、2案も3案も使われていました。

noname#220914
質問者

お礼

貴重なご意見ありがとうございます。 なんとなくですがスッキリしました。 ありがとうございます。

  • tadys
  • ベストアンサー率40% (856/2135)
回答No.2

extern はできるだけ避けたほうが良いです。 Aさんがmain.c でint abc;を定義して、Bさんがextern int abc;を宣言して利用しているとします。 Cさんがmain2.c で char *abc;を定義していて、Bさんの sub.c を利用しようとしたとしました。 このままではまずいのでCさんがchar *abc;をchar *xyz;に変更しint abc;を使用できるようにしました。 ところが、Cさんが利用していたDさんのsub2.cでextern char *abc;を宣言して利用していたのでまずいことになりました。 大規模なソフトではこの様なことが起こりかねなません。 ただし、組み込み用のマイコンではメモリ容量が制限されているので、メモリの使用量をケチケチする必要があってexternを使うこともあります。

  • catpow
  • ベストアンサー率24% (620/2527)
回答No.1

>>正直どちらのやり方が望ましいのでしょうか? ケースバイケースでしょう。 mainとsub関数が大量のデータを受け渡しするなら、externでしょうし、それほどでもないなら、ポインタ渡しにすればいいのでは? >>お互いメリットデメリットがあるのでしょうか? それはありますよ。externであれば、main,subとも、お互いにexternのデータに縛られます。 ある意味、プログラム修正の自由度が低下します。 でも、大量データの受け渡しは楽ですし、受け渡しデータが1つ増えても、修正は容易です。 引数渡しだと、externを気にせず、別のmainプログラムで使い回しが楽になります。 でも、受け渡すデータが増えると、パラメータの数がどんどん増えていくことになります。 マイクロソフトのエクセルシートなどをCやC#から操作するとき、エクセル操作の関数に渡す引数を、とても多く記述する必要がたまにありますが、これが引数渡しの欠点を表していると思います。

noname#220914
質問者

補足

すいません。 もう少し教えてください。 ありがとうございます。 関数に値を渡す場合、  1案:仮引数を用いた値渡し  2案:アドレス渡し(ポインタ)  3案:externの使用 3パターンが考えられます。 C言語では、関数の独立性をした方が良いと聞いたことがあります。 externを使用すると他の関数から 直接触れられてしまうことになるのではないでしょうか? アドレス渡しにしても、同じだと思います。 直接触れられることがない、1案が良いですが、 値の種類が多いとRAMのスタック多く消費する弱点があります。 まとめると、 値の種類が少ないときは、1案で、 多いと2案、3案となります。 ここで疑問なのが2案の存在価値です。 2案使うなら3案で良いじゃんと思います。 正直、どのような場面で線引きすれば良いか混乱しています。 ぶっちゃけ、大は小兼ねるで3案のみで良いじゃんと思うのです。 このような心の迷いを解消するアドバイスを頂けないでしょうか? よろしくお願いします。

関連するQ&A

  • C言語 extern について

    どうもこんにちは C言語でプログラムを作っています。 複数のファイルから1つのプログラムを作っていますが、あるファイルで実装した関数を別のファイルから使用する際、単にプロトタイプ宣言を行うだけでなく、extern が必要なのでしょうか? 今までは extern を使用せず、以下のように書いてました。 // main.c ファイル int func_sub(); int func_main() { return func_sub() * 2; } // sub.c ファイル int func_sub() { return 10; } これは extern を使用して、このように書かないとだめなのでしょうか? // main.c ファイル extern int func_sub(); // このexternは必要? int func_main() { return func_sub() * 2; } // sub.c ファイル int func_sub() { return 10; } 大域変数を他のファイルでも使用する場合はexternが必要ですが、関数に関してもexternを使用しなければならないのでしょうか?

  • C言語で、記憶クラス指定子extern・staticを関数に指定

    C言語の本に、「関数の定義と呼び出す側が別ソースファイルの場合、プロトタイプはヘッダーファイルに書き、定義側と呼び出し側の両方でインクルードしましょう」ということが書かれていました。 例えば、 ===code1a.c=== extern void funcB(int); static void funcA() { funcB(1); } ===code1b.c=== void funcB(int a) { printf("%d\n",a); } このような場合には、もしcode1b.cの中の関数funcBに引数を追加した場合、再コンパイルしても気づかないのでよくない。 そこで、次のようにヘッダーファイルを作り、プロトタイプはそこに書くべきだ。 ***code2b.h*** extern void funcB(int); ***code2a.c*** #include "code2b.h" static void funcA() { funcB(1); } ******code2b.c**** #include "code2b.h" void funcB(int a) { printf("%d\n",a); } 記述は以上のようなことです。 #include "code2b.h" とは、 extern void funcB(int); が書いてあるのと同じだと思います。 私が思ったのは、本の勧める方法では、 funcBを定義しているcode2b.cで、プロトタイプの記憶クラス指定子が、externになっているが良いのか(externとは、別のソースファイルで定義されているという意味ではないか)ということです。 extern, staticは、プロトタイプに書くべきなのか、関数の定義に書くべきなのか、も両方に書くべきなのでしょうか。 私の処理系では、 ・プロトタイプ宣言でexternを付けて関数定義でstaticを付ける、 ・staticを付けた関数を他のソースファイルで呼ぶ、 などの明らかに矛盾する場合は、コンパイルエラーになります。 でも、extern単独での役割はなさそうです。 他の処理系でも同じでしょうか。 (main等省略)

  • #includeとexternとCコンパイラ

    表題についてお伺いします。 (1)Cファイル内の関数をexternで渡す (2)#includeでCファイルごと定義してその関数を使う では、コンパイルは異なるでしょうか? 具体的には、 (1)はCファイルをCコンパイルする (2)はCファイルをC++コンパイルする になりますか? 前提条件:VS2013proのVC++でMFCアプリで作成するプロジェクト

  • extern "C" の利用方法に関して

    皆さんこんにちは。 extern "C"使って、 C++に書いてある関数をCでも使おうと、 もがいている最中の者です。 C++側のソース内にある、 Cでも使いたい関数に「eztern "C"」をつけ足しコンパイルに成功しました。 これから、C側でも、 C++から引用したい関数にexternをつけて、 コンパイルをしてしまおうとは思っているのですが、 C++のソース内にある関数を C側でも使うための作業としては、 これだけでいいのでしょうか? 今回作成した 「C++」のソースと「C」のソースは、 全然違うディレクトリにそれぞれ存在しているのですが、 それぞれは、認識され合うものなのでしょうか? お互いのコンパイルにあたってオプションを指定するか、 Makefileで書き換えるべき部分があるのでしょか? 笑ってしまうよな質問でしたらすいませんが、 アドバイスいただけるとありがたいです。 宜しくお願い致します。

  • C言語で他のファイルの値を参照する方法

    現在、組み込み系のソフト開発を行っています。 ファイルが、main.c と sub.c があります。 main.cで  #define kcode 0x01 と定義します。 その後、 sub.cでこのkcode の値を参照したいため、 #if kcode == 0x01 #endif と書きましたがコンパイルエラーになりました。 仕方なく、main.cで const unsigned char kcode 0x01; と書いて、sub.cで extern unsigned char kcode; if(kcode == 0x01){ } と書きました。 これしか方法がないのでしょうか? よろしくお願いします。

  • 構造体のアドレス渡し

    構造体をmain()からアドレス渡しで別関数(test.cpp)に渡し、その関数の中だけでの別関数test1()にその構造体を、値渡しでもアドレス渡しでも、渡せるのでしょうか? ちなみにmain.cppと、test.cppと、myhead.hとして分割コンパイルでやりました。 /*---------main.cpp--------*/ //ヘッダファイルで構造体宣言、test()のプロトタイプ宣言済み void main() { struct data dt[10]; ・・・・・・ test(dt); //test.cppのtest関数に構造体を渡す。 } /*---------test.cpp---------*/ void test1(??????); //test1()のプロトタイプ宣言 void test(struct data *p) //構造体をアドレス渡しで受け取った { ・・・・・ test1(?????); //test.cppで宣言したtest1関数に構造体を渡したい } どうかよろしくお願いします。

  • extern指定子の使い方

    こんにちは。 現在WindowsVistaでCプログラミングを行っています。 独習Cという本に沿って勉強しているのですが、extern指定子の使い方の所でつまずきました。 まず、サンプルプログラムを参照し、以下のような2つのファイルを作成しました。 (必要なヘッダファイルは全てインクルードしています。) ●main.c ____________________________________________________________ extern int random; void func(void); void main(void) { int i; for(i=1; i<=10; i++){ func(); printf("発生した乱数 : %d\n", random); } } ____________________________________________________________ ●func.c ____________________________________________________________ int random; void func(void) { long ltime; long utime; /*まず、time()関数とsrand()関数を使って乱数列の初期値を 毎回変更できるようにする*/ ltime=time(NULL); utime=(unsigned int)ltime/2; srand(utime); //乱数を発生させてrandomに代入する random=rand(); } ____________________________________________________________ この2つのファイルをコンパイルし、実行した所同じ整数が10個表示されました。 異なる整数を10個表示したいのですが、どうすればよいかが分からず困っています。 何か分かる方がいらっしゃれば、アドバイスをお願い致します。

  • C言語のコンパイルエラー

    次のようなコードで (宣言等は省略します) extern int main( int argc, char *argv[]) { short ret ; ret = aaa(); } static short aaa() { /* aaa()関数の処理 */ XXXXXXXXX return 1; } というようなコードをコンパイルすると ワーニングで warning: 'aaa' was declared implicitly `extern' and later `static' warning: previous declaration of `aaa' warning: type mismatch with previous implicit declaration というようなメッセージが出ます。 これは、他のソースをまねて作ってるのですが、 参考にしたコードもこのような宣言の仕方になっているのにエラーはでまでん。 何か他にもaaaという関数の定義をしなくてはいけないのでしょうか? どうもstatic宣言とexternのところがよくわかりません。 宜しくお願いします。

  • JNAでc言語ファイルの読み込み方が分かりません

    JNAでc言語ファイルの読み込み方が分かりません JNAを使用して、javaからcを読み込み動作するプログラムを作っています。 なんとなく定義は分かってきたのですが、 javaのソースコードに CLibrary.INSTANCE.printf(); のように、c言語を書き込んでいる状況なのですが、 JNAを利用した.javaファイルから.cファイルを読み込む方法はありますか? c言語の場合、.cファイルごとに分割された関数をmainが呼び出すとき、 extern void Sample(); とプロトタイプ宣言の後に Sample(); で呼び出せるみたいなので、 これを使って、 CLibrary.INSTANCE.extern void Sample(); とやってみましたが、コンパイルできませんでした;; 他にやり方がありますか? 知ってる方がいらっしゃいましたら、教えてください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • C言語でヘッダファイルにグローバル変数を宣言する

    main.hに static int a; と記述し、main.cで #include "main.h" [省略] a=10; のように使用して、-Wallをつけてコンパイルすると、main.cで使用しているにも関わらず、 'a' defined but not used という警告が表示されます。 同様に、関数においても、ヘッダファイルでstaticをつけると ‘~’ declared ‘static’ but never defined と警告されます。 静的グローバル変数などは、ソースファイル内で宣言しなければいけないのでしょうか?ヘッダファイル内で宣言しても警告が出ないような方法はありますか?

専門家に質問してみよう