C言語でのライブラリ作成時のグローバル変数対応

このQ&Aのポイント
  • C言語でライブラリを作成する際に、ライブラリ内でのみ使用するグローバル変数や関数を実現する方法はあるのか
  • Windows7とVisualC++2010を使用して開発を行う場合、C++でプログラミングすることもできるが、C言語での実現も可能か
  • あるサイトでは、特殊なマクロを使用することでC言語でのライブラリ作成時にグローバル変数を実現する方法が紹介されているが、他にも方法はないのか
回答を見る
  • ベストアンサー

ライブラリ作成時のグローバル変数の対応(C言語)

C言語を用いてライブラリを作成しています。 ライブラリは機能ごとにファイルを分けています。 今、ライブラリの中でのみ使用するグローバル変数やグローバル関数が必要になりました。 このグローバル変数や関数は複数ファイルで参照するため、static宣言はできません。 しかし、このグローバル変数や関数は公開する必要はありません(ライブラリの中でのみ使用します)。 このようなことをC言語で実現するためにはどうしたらよいのでしょうか? 開発環境は Windows7 VisualC++2010 です。 VisualC++2010を使うなら C++で書けばいいのではないかといわれそうですが、 C言語でプログラミングしたいのです。 以下のようなサイトがあったのですが、これを使うしかないでしょうか? http://0xcc.net/blog/archives/000108.html

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8527/19385)
回答No.2

スレッドセーフを意識する場合、ライブラリ内でグローバル変数を持つ事は許されません。 「一連の呼び出しの中で、グローバルなスコープが必要」なのであれば、fopen関数でやっているように「開始関数で一意のハンドラを返し、一意のハンドラを指定して一連の呼び出しを行ってもらい、終了処理で一意のハンドラを開放する」と言うような書き方をしないといけません。 fopenが「グローバル変数で、次に使える、空いているハンドラの番号を持っている」と言う実装があったとします。 もし、メインのスレッドでfopenが3番のハンドラを返そうと準備している真っ最中(fopenから、まだ帰って来てない状態)に、サブのスレッドがfopenを呼び出して3番のハンドラを受け取ったら、どうなると思いますか? メインのスレッドも、サブのスレッドも、どっちも「3番のハンドラ」を受け取ります。 メインとサブで異なるファイルをオープンしているのに、ライブラリがグローバル変数で「次の空きは3番」なんて情報を持っていた所為で、両方とも「3番」を受け取ってしまったのです。 もちろん、実際のfopenは「マルチスレッドであっても一意」になっているヒープ領域を用いて「スレッドが切り替わっても大丈夫」な作り(つまり、スレッドセーフ)になっているので、こういう事は起きません。 ライブラリ内にグローバル変数を作ると「マルチスレッド禁止」になっちゃうので、スレッドセーフにするなら、グローバル変数は作ってはいけません。ライブラリ内の変数は、必ず「外にスコープを持たないstatic変数」にしないといけません。

cyacya2000
質問者

お礼

スレッドセーフについては完全に考えから抜けていました。 やはり、グローバル変数は作らないようにします。 ありがとうございました。

その他の回答 (2)

  • chie65535
  • ベストアンサー率43% (8527/19385)
回答No.3

>ライブラリ使用者がライブラリ内でしか使用しないグローバル関数やグローバル変数と同じ名前を使用しても問題ないレベルを希望しています。 C言語ではそれは不可能。言語の仕様上、そういう事は「出来ない仕様」になっています。 例えば、fopenを使うと、fopen等のファイル入出力関数群がグローバルに扱う「_iobuf」と言う変数がリンクされます。 当然、ユーザーは「_iobuf」と言う名前のグローバル変数を作る事は許されません。「同じ名前は許されない」からです。 そのため、Cの標準ライブラリでは、グローバル変数やシンボリック定数は「アンダースコアから始まる」と決められ「ユーザーはアンダースコアから始まる変数や定数を作ってはならない」と決めました。 とうぜん、そうした理由は「ライブラリ内でしか使用しないグローバル関数やグローバル変数と同じ名前は、ユーザーは使用出来なくなる」からです。 なので、最初から「ユーザーは使うな」と決めたのです。 「使うな」と禁止しておけば、バッティングする事は有り得ません。

cyacya2000
質問者

お礼

早速のご回答ありがとうございます。 おっしゃっている意味はわかるのですが、 VC++2010のオプションなどで救える手段があれば教えていただきたいのですが。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「ある程度」で妥協していいなら「外部から #include するヘッダ」と「内部からのみ #include するヘッダ」に分けるのが簡単.

cyacya2000
質問者

お礼

早速のご回答ありがとうございます。 公開しないということなら、ヘッダを分けることでもある程度は実現できますが、 ライブラリ使用者がライブラリ内でしか使用しないグローバル関数やグローバル変数と同じ名前を使用しても問題ないレベルを希望しています。

関連するQ&A

  • C言語のStatic変数について

    現在、C言語の勉強しながらゲームプログラムにチャレンジしています。 二つの関数で利用する変数を作りたかったので、Static宣言された変数を容易しました。 ですが、この変数、一度処理が終わると当面使わない変数なのです。 (ただし、処理途中は何度も呼び出されるので値は保持しなければいけません) よって、メモリ上に延々居座られるのが邪魔に思えて仕方ありません。 実際、大したことないだろうとは思うのですが。 このStaticで宣言された変数を、自分の好きなタイミングでメモリ上から解放するような処理はできませんか? もしくはメモリ上に居座ることのない処理の仕方などありましたら、 考え方を教えていただけるとうれしいです。よろしくお願いします。

  • C言語 関数の戻り値と自動変数

    かなり基礎的な質問になるのですが、疑問に思うことがあり、質問をさせていただきます。 関数内で宣言した変数を戻り値として使う場合ですが、ポインタなどではなく実体の場合でも、静的変数として宣言をしたほうが良いのでしょうか? 現実的に考えると、プログラムが関数から出て、呼び出した側の関数が戻り値を受け取るまでの瞬間に、その領域が書き換えられる可能性は極めて低いと思うのですけど、C言語の仕様としてはどうなのでしょうか? 関数内で宣言した戻り値に使う変数には、必ずstaticをつけた方が良いのでしょうか? もしおわかりでしたら教えて下さい。

  • 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 と警告されます。 静的グローバル変数などは、ソースファイル内で宣言しなければいけないのでしょうか?ヘッダファイル内で宣言しても警告が出ないような方法はありますか?

  • C言語のローカル変数の使い方について質問です。

    C言語の変数に関しての質問です。 グローバル変数を使わずに、関数内で宣言したローカルの変数を別のソースファイルで使用することって可能ですか? 例えば、a.cというソースファイルと、b.cというソースファイルがあります。 a.cの関数内で"FILE *fp;"と宣言したローカル変数を、b.cの関数内で共有して使うことはできるのでしょうか。 また、"fp"に直接アクセスはできなくても、間接的にアクセスできる方法があれば教えてください。 下に記述しているのは例え用に適当に書いたプログラムです。 --------------------- a.cのソースファイル --------------------- void Temp(void) { char file_name[128] = {}; errno_t error; FILE *fp; // ←この変数を別のソースで使いたいです scnaf_s("%s", file_name, 128); if(error = fopen_s(&fp, fname, "rb") != 0) { printf("ファイルがオープンできません"); return 0; } fclose(fp); } --------------------- b.cのソースファイル --------------------- void Temp2(void) { int size; // ここでa.cのTemp関数で宣言されている"fp"を使いたい fseek( fp, 0, SEEK_END ); fsize = ftell( fp ); fseek( fp, 0, SEEK_SET ); }

  • C言語での変数宣言の場所

    今まで2年ほどJavaを使っていましたが、最近になってCを使う必要が出てきました。Cは大学の頃に授業で学んだ程度のレベルです。 それはさておき。 JavaやC++ではメソッド内のどの場所ででも、新たな変数を宣言して使用できますが、Cでは関数内の最初の方でしか宣言できないですよね? 先日、その事を意識せずに、Javaと同じように変数を関数の任意の場所で宣言しているようなCのソースを書き、gccでコンパイルしたところ、コンパイルが通ってしまいました。 その時のファイルは「.c」ファイルです。 このソースはC++のソースとして、コンパイラが認識してしまったのでしょうか?拡張子が「.cpp」ではなく「.c」のままでしたが、コンパイラは拡張子ではなく、ソースを読み込んでから、そのプログラムがCなのかC++なのか判断しているのでしょうか? いまいちピンと来ないので、どなたか解説お願いします。

  • C++での静的ライブラリの作成方法

    C++での静的ライブラリの作成方法 今まで独学でC++を勉強してきたのですが、既存ライブラリのラッパーを作りたいと思います そこで、色々なサイトなどで調べてみたのですが、いまいちライブラリというものについて納得の出来る解説のあるサイトが見つからなかったので、質問させて下さい まず私が元にするライブラリの構成は hoge.h foo.lib bar.lib となっており、その関数などを使用する独自型のクラスや、それをさらに扱うクラスなどを作っています その場合、ふたつのクラスをひとつのlibファイルに一緒にしてもいいものなのか、 はたまた分けてそれぞれlibファイルにするのか、 複数できたヘッダはプロジェクトに追加するときどれを入れるのか、 インクルードやリンクはどこに張ればいいのか、 libファイルにヘッダは含まれているのか、など 基本的なことが全然わからず、身近に聞ける人もいなくずっと手探り状態です よろしければ全体のファイル構成や作り方、使い方などの基本的なことから教えて下さい あと別件なのですが、クラスのインスタンスが生成されたときにメンバ変数はメモリに動的に配置されると思うのですが、メンバ関数はどうなるのでしょうか? インスタンスごとに同じく生成されるのか、宣言の時に既に一箇所に用意されていて、毎回そこに飛ぶのでしょうか? よろしくお願いします!

  • C言語のライブラリ

    C言語の初心者でただいま勉強中です。 今ちょうど、関数のところでライブラリについて 勉強しているのですが ライブラリのソースがどうなっているのか気になっております。 どうにかしてライブラリのソースを見る方法はないでしょうか?

  • CとC++の変数宣言について

    なぜC言語では変数の宣言をブロックの先頭でする必要があるのかがわかりません。 またC++がどこででも宣言できるのもなぜか教えてください

  • Linuxで、標準Cライブラリが読み込まれず、C言語プログラミングができません・・・

    僕の問題はタイトルの通りで、標準Cライブラリが読み込まれていないようで、C言語プログラミングができません。 ubuntuのオフィシャルから日本語ローカライズドDesktopCDをダウンロードして、空のHDDにインストールしました。 ですが、gnome-terminalからccコマンドでプログラムをコンパイルしても、標準Cライブラリにあるはずの<stdio.h>が認識されず、続くprinft関数も読んでくれません。 これはどうしてでしょうか?LinuxはデフォルトでCやらJAVAやらのプログラミングの環境が整っているものだと思っていたので、戸惑っています。何か、セットアップが必要なのでしょうか。 ちなみに、gccでも、標準ライブラリは読み込まれませんでした。

  • C言語にはJavaのような豊富なライブラリはないんでしょうか?

    C言語にはJavaのような豊富なライブラリはないんでしょうか? JavaにはTreeSet, Vector, LinkedListなどの便利なライブラリがありますが、C言語にはこういったのはないのでしょうか?string.hやstdio.hなどはあるのは知っていますが、Javaほどライブラリにある関数が少ないと思いますが、どうなんでしょう?CでLinked Listを使いときなどは自分で書くしかないのでしょうか?