1

この質問に続いて、私は以前に尋ねました。inlineグローバル スコープで関数を定義する方法を知りたいです。

test.h で関数を宣言 し、main.cで定義して、test.c から呼び出したい。inline

main.c と test.c の両方#include "test.h"(コード サンプルについては、上のリンクをクリックしてください)。

これは基本的に、ユーザーが有効/無効にできるある種のコールバック関数です。また、関数が定義されているファイルは 1 つだけです。

inlineコンパイラへの単なる提案であり、最新の CPU では大きな違いはありませんが、これは 8 ビット マイクロコントローラ用であり、実際に必要になります。

編集:

このインライン関数を呼び出す関数が test.c にあります。呼び出しを main.c で定義された関数の本体に置き換えたいだけです。それが理にかなっていることを願っています。

4

4 に答える 4

2

ほとんどの 8 ビット マイクロコントローラ コードは、C89 に近い言語で書かれており (インライン アセンブリなどの拡張機能がよくあります)、C99 まで正式inlineに C の一部ではありませんでした。したがって、まず最初に、コンパイルしている標準を特定し (存在する場合) 、拡張機能 (つまり、C99 インラインではない) の場合は、コンパイラのマニュアルを参照してください。そのプログラミングの領域では、コンパイラ マニュアルが C 標準よりも優先されます。inline

Per C99bothmain.ctest.cboth が同じ関数を呼び出す必要があり、それをマークする必要がある場合、関数は翻訳単位 (つまり、「.c」ファイル) にまたがることができないinlineため、ヘッダーで定義する必要があると思います。inline

例えば:

test.h:

static inline int add(int a, int b) { return a + b; }

main.c:

#include "test.h"
void main(void)
{
   int x = add(10,15);
}

test.c:

#include "test.h"
int test(void)
{
   int x = add(10,15);
   return x;
}

編集:inline C99 の使用方法のより良い説明については、こちらを参照してください: C99 マルチファイル プロジェクトでインライン関数を宣言する方法は?

ただし、これにより、結果のオブジェクト コードであらゆる種類の奇妙な動作が発生する可能性があります。たとえば、主要なMCU 製造元のコンパイラ (意図的に名前を伏せます) が、関数をインライン化する代わりに、特定の翻訳単位でinline関数のオブジェクト コードを生成するのを見てきました。ファイルはいくつかの場所に含まれており、多くの関数が含まれていたため、リンカもデッド コードを削除できず ( を参照)、関数が実際に使用されなかったため、パフォーマンスを改善できなかったため、コード ベース全体で全体的な ROM 使用量が大幅に増加しました。技術的にはインラインの正しい使用法でしたが、インライン化されました。 #included--gc-sectionsgcc

この特定の問題に対する私たちの解決策は、すべての関数をマクロに変換することでした (これにより、 で意図されたパフォーマンス上の利点が得られましたinline) が、代わりのアプローチは、宣言から を削除し、定義を 1 つのファイルinlineに移動することでした。.c

TL;DR: MCU に使用inlineする場合は、1) コンパイラのマニュアルを参照し、2) 生成されたオブジェクト コードに注意してください。

于 2015-02-19T13:15:19.703 に答える
2

問題の関数がコールバックであるとあなたが言っていることを意味すると仮定すると、コールバックをインライン化することはできません。意味がありません。コールバック呼び出しは通常、関数ポインターを介して発生します。コンパイラーがその値が一定であること (およびコンパイル時に既知であること) を証明して、呼び出しを置き換えることができるとは期待できないと思います。インラインコードで。

于 2015-02-19T12:59:07.140 に答える
-1

それが機能する方法はまさにそのようです。関数の定義は1つだけです。それが関数だと言って、int add(int x, int y);それを定義しますmain.c

main.c :

int add(int x, int y)
{
    return x + y;
}

それを別のcファイルで使用したい場合、必要なのはこれだけです

test.c

int add(int x, int y); /* just a declaration, a function prototype */

int addWrapper(int x, int y)
{
    return add(x, y);
}

このようにコンパイルします

gcc -Wall -Werror main.c test.c -o some_output_file_name

リンカが関数定義を見つけます。

関数がコンパイルされたファイルのいずれにも定義されていない場合、

Undefined reference to `int add(int x, int y);' in ...

エラーが出ます。

コンパイラに関数本体を挿入させたい場合は、関数本体を自分で挿入し、プリプロセッサ マクロを使用します。

header.h

#define add(x,y) ((x) + (y))

その後

#include "header.h"

int addWrapper(int x, int y)
{
    return add(x, y);
}

に置き換えadd(x, y)ますx + y

関数が返された場合、voidこれを使用するのが良いトリックです

#define inlinedFunction(parameters) \
    do {                            \
        /* function body here */    \
    } while (0)

マクロ定義の各行の最後に継続バックスラッシュを追加する必要があります。

于 2015-02-19T12:59:18.797 に答える