web-dev-qa-db-ja.com

関数が外部からアクセスされていることを明確にする方法は?

これはC固有の質問です。 .hファイルを介していくつかの関数のみを公開し、翻訳ユニットの境界内で可能な限りすべてを維持しようとしています。つまり、ファイルレベルのオブジェクトにstaticリンケージを与えています。

ここで、いくつかの関数を他のモジュールから呼び出す必要がありますが、直接呼び出す必要はありません。私のモジュール/ファイル/翻訳ユニットは他のモジュールをサブスクライブし、関数へのポインターを渡します。次に、特定のイベントで、いくつかの引数を使用してポインターが呼び出されます。

したがって、これらの関数があいまいな場所から呼び出されていることを非常に明確にする方法を考えています。

  • それらはstaticまたはexternである必要がありますか(そしてそれらを.hで公開します)?
  • 関数の名前にいくつかのヒントを含める必要がありますか?
  • それとも、「Xによって呼び出された」というコメントを入れるだけで十分ですか?
9
Vorac

コンパイル単位(ファイル)の観点から、あなたが気にかけるべき唯一のことは、関数が外部で利用可能であるかどうかです。それを使用可能にすることは、それが呼び出されることを意図していたことを意味し、それらの呼び出しが発生することを想定して操作する必要があります。関数自体に関する懸念は、そのエントリポイントから始まります。そもそも制御がどのようにそこに到達するかは、それを実現するコードにのみ重要です。

私が知っているCのすべての実装におけるリンケージはシンボリックであるため、関数を呼び出すものはすべてそのシンボルを参照する必要があります。

_foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */
_

foo()を誤ってstaticと宣言した場合、プログラムはリンクされません。 static以外と宣言すると、呼び出されない公開された関数があります。関数が使用されているかどうかに関する質問は、オブジェクトファイルのシンボルテーブルをダンプするか、ソース内で検索することで解決できます。

2
Blrfl

そのため、これらの関数が不明瞭な場所から呼び出されていることを非常に明確にする方法を探しています。

「あいまい」を定義します。
メソッドは明確に定義された「インターフェース」を通じて公開する必要があり、Shivan Dragonがすでに示唆しているように、それらの「インターフェース」are .hファイル。別のプログラムに「正しい」ヘッダーファイルを指定しないと、メソッドを呼び出すことができません。

それらは静的であるか外部である必要がありますか(そしてそれらを.hで公開する必要があります)?

staticmightインスタンスデータを含むクラス[のような構成]がない限り、問題ありません。
externyo実際にはまったく実装しないことを意味します。リンクプロセス中に、他の場所から実装が「取得」されます。

関数の名前にいくつかのヒントを含める必要がありますか?

それとも、「Xによって呼び出された」というコメントを入れるだけで十分ですか?

絶対違う。

このようなコメントは、どんなに意味のあるものであっても、書き終えた瞬間に時代遅れになります。

1
Phill W.

私はまだそれらをstaticにし(それらは誰にでもリンクされて呼び出されることを意図していません)、それらの目的をそれらの名前で外部関数に提供されるコールバックとしてマークします。

static隠すことができるものを、隠すことができる限り隠そうとしているからです。

A)、コメントが古くなっている、およびb)コールバックが提供された場所で、この関数がそのように使用されることが意図されていることが明らかになったため、名前にそれらをマークします。命名規則に従わない関数のアドレスを取得している。

0
Sebastian Redl

スコープ修飾子は、「十分に近い」ドキュメントの形式としてではなく、主にコンパイラの情報として使用する必要があります。特にstaticを使用すると、Cコンパイラは、現在のコンパイラで動作する場合でも、コールバックとしても含めて、モジュールの外部から関数を使用できなくすることができます。

もちろん、コードにコメントを追加する必要があります。これは、混乱を招く可能性がある状況であることがわかるためです。異常または予期しないものには、適切なコメントが必要です。しかし、他の回答で述べられているように、コメントは未読になったり、古くなったりする可能性があります。

したがって、残っている唯一のオプションは、関数に名前を付けて、それがコールバックであることを示すことです。私が見たほとんどの例は_callbackまたは_cb接尾辞、またはcb_を接頭辞として。コードでコールバックが異常な場合は長い形式を使用し、一般的な場合は短い形式を使用します。

0
Jonathan Giddy

モジュール内でコールバック関数が定義されていて、ユーザーが自分のものを提供しない場合は、初期化フェーズでプレースホルダーを使用できると思います。プレースホルダーは通常、enumであり、内部で適切なstatic関数に変換されます。

0
lorcap