2016-08-30 17 views
1

私はC言語でのプログラミングでnewbyです。誰かが私にどのように*(float*)aのような宣言を "読む"かを説明し、いくつかの例を段階的に挙げることができますか?Cのポインタ型宣言を読む

ありがとうございます!一般的に

+4

これは宣言ではありません。 'float'へのポインタにキャストされた変数' a'を逆参照しています。 @EugeneSh。 –

+0

もっと説明してください!ありがとう:) –

+0

[C++のポインタ変数と参照変数の違いは何ですか?](http://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer -variable-and-a-reference-variable-in) – RCB

答えて

1

、あなたが優先順位と演算子の結合性の両方を気にする必要があります。この場合table

、間接参照とキャスト演算子が同じ優先順位を持ち、両方の右から左へassociativesです。これは、各演算子が右側にあるものに適用され、同じ優先順位を持つため、逆参照演算子は、その右側にあるキャスト演算子の後に適用されることを意味します。

したがって、実行される操作の順序は次のとおりです。a - >キャストする(float *) - >逆参照する。

EDIT:単項演算子(逆参照、キャスト、否定など)がある場合、その演算子は常に右から左への連想であり、計算された右辺のすべての式の後に適用されます。したがって、私たちのケースでは、上記の表を見ることなく右から左に演算子が適用されると言うことができます。

+1

ここでは、優先順位が関係するかどうかはわかりません - 左の '* 'が(構文的に)適用できる** only **のことは'(float *)a'の結果です。 –

+0

ありがとうございました! @Davide Visentin –

+0

'(int *) - >(float *)'おそらく。 – sjsam

0

*(float *)aは宣言されていません。 キャスト式です。この特定のケースでは、aの値をとり、それをfloatへのポインタとして扱い、その結果を逆参照します。おそらくaは異なる型へのポインタであり、floatへのポインタとして扱いたいと考えています。

限りが懸念されているポインタ宣言として...

単純なポインタ宣言は

Tが(潜在的にconst又はvolatileなどの修飾子を持つ)任意のタイプである
T *p; // p is a pointer to T 

ように見えます。 オブジェクトのタイプは、 pは "Tへのポインタ"です。型指定子と修飾子の組み合わせによって完全に指定されます。T宣言子*pです。

宣言子は、宣言されているものの名​​前と、型指定子で提供されていない型情報を導入します。上記の宣言では、*pが宣言子です。これは、オブジェクトの名前(p)と追加の型情報(へのポインタ)を提供します。

T a[N]; // a is an N-element array of T 
T f(); // f is a function returning T 

配列:あなたは

T* p; 

としての宣言を記述した場合でも、それは

T (*p); 

としてを解析され、同じことは配列や関数の宣言のために保持していることに注意してください-nessの値がaの場合は、宣言子a[N]で与えられ、関数の値がfの場合宣言者f()によって。

あなたがそうのように、[]()*を組み合わせることができます宣言と式の両方で

T *a[N]; // a is an N-element of pointers to T 
T (*a)[N]; // a is a pointer to an N-element array of T 
T *f(); // f is a function returning pointer to T 
T (*f)(); // f is a pointer to a function returning T 

、単項*は、postfixの[]または()のいずれよりも低い優先順位を持っているので、*a[N]*f()があるを解析されました*(a[N])*(f())となります。 aをポインターの配列ではなく配列へのポインターにする場合は、aを明示的にグループ化して(*a)[N]とする必要があります。

あなたは、さらにそのようなこれらの要素を組み合わせることができます。

T **p;  // p is a pointer to a pointer to T 
T a[N][M]; // a is an NxM array of T 
T (*f[N])(); // f is an array of pointers to functions returning T 
T (*f())[N]; // f is a function returning a pointer to an array of T 
T *(*(*a[N])())(); // a is an array of pointers to functions returning pointers to functions returning pointers to T 

はい、機能は他の機能に配列とポインタへのポインタを返すことができ、そしてはい、構文はファンキーに見えるが、仕事を宣言子方法から論理的に以下の場合。あなただけのポインタ名(任意のパラメータと共に)関数呼び出しを置き換える:C標準ライブラリからsignal機能:

T (*a)[N] => T (*f())[N], a => f() 
T (*f)() => T (*g())(), f => g() 

は、ここでの例です。

void (*signal(int sig, void (*func)(int)))(int); 

は、この宣言を読んで、左端の識別子で始まり、上記の優先順位の規則を適用し、あなたの方法を動作するように:それは別の関数へのポインタを返す関数です。任意の関数パラメータに再帰的にそれらの規則を適用します。

 signal          -- signal 
     signal(      )   -- is a function taking 
     signal( sig     )   -- parameter sig 
     signal(int sig     )   -- is an int 
     signal(int sig,  func  )   -- parameter func 
     signal(int sig,  (*func) )   -- is a pointer 
     signal(int sig,  (*func)( ))   -- to a function taking 
     signal(int sig,  (*func)( ))   --  unnamed parameter 
     signal(int sig,  (*func)(int))   --  is an int 
     signal(int sig, void (*func)(int))   -- returning void 
     *signal(int sig, void (*func)(int))   -- returning a pointer 
    (*signal(int sig, void (*func)(int)))( ) -- to a function taking 
    (*signal(int sig, void (*func)(int)))( ) -- unnamed parameter 
    (*signal(int sig, void (*func)(int)))(int) -- is an int 
void (*signal(int sig, void (*func)(int)))(int); -- returning void 

ので、signalは、関数へのポインタを返す関数です。 signalは2つのパラメータを取ります.1つはプレーンint、もう1つはintを受け取り、voidを返す関数へのポインタです。関数の宣言では、パラメータ名を指定する必要はありません。それらは対応する関数の定義で指定する必要があります。

+0

例:(float *)xfunction(x、y、z)? @John Bode –

+0

@M_sansa - 関数* call *であり、戻り値は 'float'へのポインタにキャストされています。 –