17

私はC言語で作業していて、以前に他の誰かが書いたコードを変更しています。私はいくつかのことに苦労していて、何が起こっているのかをできるだけ理解しようとしています。それで、私の質問が述べたように、関数を作成するときstatic inline voidとの違いは何ですか?void長い投稿を前もってお詫びしますが、私が調査を行ったことを知ってもらいたいのですが、私が見つけたものがわかりません。

私はそれの説明がstatic私を混乱させるのを見つけました:

静的指定子は、関数が他のファイルから参照できないことを示します。つまり、名前はリンカーによってエクスポートされません。

これを読んで、関数を参照することは関数を呼び出すこととは異なると思いますか?この関数は別の.cファイルから呼び出されるためだと思います。その場合、関数を参照しているのは何ですか?

同じウェブサイトでインライン関数を説明しているのですが、どういう意味かわかりません。

__inlineキーワードは、関数呼び出しのすべてのインスタンスの関数定義内のコードを置き換えるようにコンパイラーに指示します。ただし、置換はコンパイラの裁量でのみ発生します。たとえば、アドレスが取得された場合、または関数が大きすぎてインライン化できない場合、コンパイラーは関数をインライン化しません。

は???

どんな助けでも大歓迎です、そして私はもう一度ひどく長いポストをお詫びします。

以下はfile1.cにあります(私はそれが重要ではないと思うので一般的な名前を使用します)

COMPLEX cNoiseSample;
CGauss( &cNoiseSample, loopbackRadio->pState );

以下はfile2.cにあります

static inline void CGauss( COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState )
{
    //code
}
4

6 に答える 6

16

static別のコンパイルユニット(ソースファイル)から参照できないことを意味します。「参照される」とは、呼び出されるか、名前で参照されることを意味します。たとえば、関数ポインタに割り当てられます。

inline関数のコードは、分岐先の個別の関数として生成されるのではなく、呼び出された場所でインラインで生成される必要があるというコンパイラーへのヒントです。これは通常、パフォーマンス上の理由で行われます。Microsoftの見積もりに対処するには:

アドレスが取得された場合、または関数が大きすぎてインライン化できない場合、コンパイラーは関数をインライン化しません。

インライン関数は、別個のエンティティとして存在しないため、アドレスがありません。そのコードは、呼び出し元のコードとシームレスに絡み合っています。したがって、関数のアドレスを取得する場合(たとえば、ポインターに割り当てる場合)、コンパイラーはそれを実際の関数として生成する必要があり、インライン化することはできません。

void関数が値を返さないことを意味します。


コードサンプルを見ると、 file1.cCGauss()から呼び出されているのに対し、file2.cは独自のプライベートバージョンを呼び出しているという別の定義があると思います。それか、file1.cがfile2.cを実行しています。これは厄介でしょう。#include

于 2012-06-12T14:44:44.547 に答える
8

static複数のソースファイルがある場合にのみ意味があります。static別のファイルの関数から関数または変数にアクセスできないことを指定します。

inlineは、特定の場合にコードを高速化するコンパイラ最適化です。関数を呼び出すときはいつでも、それに関連するオーバーヘッドがあります。したがって、コンパイラが実行できることは、インライン化されたコードを(ほぼ)コピーして貼り付けることにより、関数をまとめて削除することです。

インライン化の例を次に示します。

int dotproduct(int x1, int y1, int x2, int y2) {
    return multiply(x1,x2)+multiply(y1,y2);
}

inline int multiply(int a, int b) {
    return a*b;
}

コンパイラはこれを次のように変換します。

int dotproduct(int x1, int y1, int x2, int y2) {
    return x1*x2+y1*y2;
}

ファンシーになりたい場合は、ドット積関数をインライン化することもできます;)

inlineキーワードは、特定の関数をインライン化するためのコンパイラーへの単なる微調整であることに注意してください。それはそれ自身の判断に応じて実際にそれをするかもしれないし、しないかもしれない。

于 2012-06-12T14:43:50.240 に答える
3

静的キーワード

C関数の静的定義とは、(ドキュメントにあるように)この関数にアクセスできるのはそれが定義されているソースファイルからのみであることを意味します。この意味での「参照」という用語は、この関数を呼び出すか、たとえば関数ポインターを取得することを意味します。 。

インライン化

通常、Cで関数を作成すると、コンパイラはこの関数のマシンコードを生成します。

foo:
   /* some machine code */
   ret

この関数を呼び出すたびに、コンパイラは次のような命令を挿入します。

  call <foo>

呼び出し元のマシンコードに挿入します。これは、「fooにジャンプし、そこで見つけたものを実行し、ret命令に遭遇したら、この場所に戻る」ことを意味します。

対照的に、インライン関数の場合、コンパイラは個別の関数foo()を生成しませんが、代わりに関数fooのマシンコードをすべての呼び出しサイトに挿入します。このコードを実行すると、同じ効果があります。

では、なぜそれを行うのでしょうか。コードのインライン化には、2つのジャンプ(呼び出しとそれぞれのret)を節約できるという利点があります。これにより、コードの実行が少し速くなります。欠点として、呼び出し可能な関数のコピーを1つだけ持つのではなく、すべての呼び出しサイトにマシンコードを挿入するため、コードが大きくなります。そのため、通常は小さな関数のみをインライン化します。

また、インライン関数への関数ポインタを取得できず、インライン関数にブレークポイントを簡単に設定できないため、デバッグが困難になります。

したがって、インライン化は最適化オプションとしてコンパイラーに残され、C ++のインライン、インラインディレクティブ、GCCの__attribute((inline))などのキーワードを使用することで、ここでインライン化を試す価値があるかもしれないというヒントをコンパイラーに与えるだけです。 。

于 2012-06-12T14:48:47.447 に答える
1

上記のすべてに加えて、上記を読む前に、cプログラミングがどのように機能するかを理解することが重要です。単純にオープンコードを書く場合、

Setup(){
    int MainVar
}

MyRoutine(){
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

そうすれば、誰でも2番目のプログラムから直接MyRoutine.myVar1にアクセスできます。MyRoutineで使用する前に、myVar2の値を変更できます(1.保護されていない場合、2。存在していることを知っている場合、3。何をしているのかを知っている場合)。元のプログラマーが意図した。

あなたが銀行プログラムを書いていて、コードを脆弱なままにして、誰かがあなたのルーチンの他の銀行からのWITHDRAWLを変更せずにDEPOSITの値を変更できると想像してください。他の誰かがやって来て、その値を2または10ずつ変更する別のプログラムを作成し、存在しない場所でお金を稼ぐことができます。ただし、コード、ルーチン、メソッド、または変数の前にSTATICを付けると、これらの項目にアクセスしたり、表示したり、最も重要なことに別のプログラムで変更したりすることはできません。

静的はいつでも使用でき、ルーチン全体を閉じたり、個々の変数を閉じたりすることができます。したがって、他の人がコードの特定の側面に変更を加えることを許可しますが、保護する必要のある側面は保持します。

MyRoutineにStaticを設定すると、誰かが別のプログラムからMyRoutineを実行できなくなります。MyVarsはMyRoutine内で宣言されているため、別のプログラムからアクセスすることはできません。ただし、プログラム内の他の場所で宣言されたMainVarという変数がある場合は、アクセス可能です。

Setup(){
    int MainVar  // This can be accessed from outside this code
}

static MyRoutine(){  // Because of static these vars are not
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

そしてここでは、静的な変数のみが保護されます。myVar3は他の場所から読み取られ、交換が完了したことを別のルーチンに通知できます。

Setup(){
    int MainVar    // This can be accessed from outside this code
}

MyRoutine(){
   static int myVar1;  // This can NOT be accessed from outside this code
   static int myVar2;  // This can NOT be accessed from outside this code
   bool myVar3;        // This can be accessed from outside this code
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}
于 2018-05-20T20:59:58.537 に答える
0

staticは、基本的に、関数が定義されているソースファイルの外部で「非表示」になっていることを意味します。

inlineは、コンパイル時に関数が呼び出される各場所で、基本的に関数呼び出しコードをソースに直接代入するようコンパイラーに要求します(関数呼び出しを関数のコードに置き換えるなど)。ただし、発生する保証はありません。コンパイラに提案するだけです。

それよりも技術的で、はるかに良い答えが得られる可能性がありますが、簡単な言葉で言えば、これが用語の意味です。

于 2012-06-12T14:46:14.967 に答える
-2

とても簡単です。

void*voidポインタ(任意の参照)を返すことができます。しかしvoid、何も返すことはできません。

例えば:

1)

int x=7;

void *abc()    
{    
    return &x;    
}     

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

出力:7

2)

int x=7;

void abc()    
{    
    return &x;    
}

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

でコンパイルエラーが発生しますprintf("%d\n",*((int*)(abc())));

void何も戻せないから。

于 2019-01-06T00:39:41.857 に答える