void * function()は関数へのポインターですか、それともvoid *を返す関数ですか?


26

の意味がわかりませんvoid *function()
それは関数へのポインタvoid*ですか、それとも関数が戻りますか?私は常にポインタを返す再帰関数としてデータ構造で使用しましたが、マルチスレッド(pthread)でコードを見たとき、同じ関数宣言があります。今、私はそれらの違いが何であるか混乱しています。


5
@goodvibration Cはフォーマットフリーになりました(そしてC ++はこれを「継承」しました)。でも、void*function();構文的に正しいです。たとえばPythonの場合、彼らは別の決定を行いました-フォーマットは構文の一部です。私見、両方の方法には長所と短所があります。
Scheff

3
@goodvibration javaのようなものを取得するほど、プログラマーがやりたいことからプログラマーを保護しようとするほど、;)
idclev 463035818

2
@goodvibrationオプションが少なく、柔軟性が低くなります。そして、彼らがそれをしたのは数十年前のことだということを覚えておいてください。後で文句を言うのは簡単です... ;-)
Scheff

2
C言語でvoid *function()は、任意の数の引数を取り、逆参照されるとvoid型の値を返す関数です。C ++では、void* function()引数をとらず、pointer-to-voidの値を返す関数です。あなたはあなたが尋ねている言語についてあなたが決心するべきです。
スティーブンM.ウェッブ

1
@ StephenM.Webbを逆参照することはできませんvoid *。結局のところ、できたとしても、あなたはどうしますvoidか?
ファビオは19:10

回答:


38

関数には戻り型がありvoid *ます。

void *function();

したがって、そのような場合は常に、シンボル*を関数名から分離することを好みます

void * function();

そして Jarod42、コメントで指摘されているように、後続の戻り値の型を使用してC ++で関数宣言を書き直すことができます

auto function() -> void *;

関数へのポインタを宣言したい場合は、

void ( *function )();

または

void * ( *function )();

または、関数へのポインタを返す関数へのポインタ

void * ( *( *function )() )();

2
だからこそ、私は書くことを好むvoid* function();。それはそれほど魅力的ではありません... ;
Scheff

私は宣言するコード内void * reader();に、その後pthread_create(&thread1,null,reader,reader_arg)の代わりにpthread_create(&thread1,null,&reader,reader_arg)
user9515151

1
@Scheff:またはauto function() -> void*(C ++)。:)
Jarod42

3
または、関数へのポインタを返す関数へのポインタ それが何のtypedefためにあるのか... ;-)
Andrew Henle

1
@AndrewHenle typedefでは問題はありません。typedefまたはエイリアス宣言なしで宣言が使用されると問題が発生します。:)
Vlad from Moscow

7

Cの構文の問題が不明な場合は、cdeclユーティリティ(オンラインバージョン)を使用して解釈します。C構文と英語の間で変換します。

たとえば、私はあなたの例を入力しvoid *foo()、それが返されました

fooをvoidへのポインタを返す関数として宣言する

他の構文がどのように見えるかを確認するために、私は入力declare foo as pointer to function returning voidしてそれを返しました

void(* foo)()

これは、1つの式にタイプキャスト、スター、またはブラケットの複数のレベルがある場合に特に役立ちます。


2

へのポインタを返す関数voidです。

宣言を次のように考えてください。

void *(function());

これは、以下を返すvoid(または何もしない)関数です。

void (*function2)();

上記の宣言を次のように考えてください。

void ((*function2)());

これらを作成するはるかに簡単な方法は、typedefs を使用することです。

typedef void *function_returning_void_pointer();
typedef void function_returning_nothing();

function_returning_void_pointer function;
function_returning_nothing *function2;

これにより、通常、関数ポインターに関する混乱がなくなり、読みやすくなります。


0

C / C ++の宣言は、演算子の優先順位に従って、識別子から外側に向かって読み込まれます。

ウィキペディアのC / C ++演算子の優先順位表をざっと見てみると、関数呼び出し演算子の()方が間接演算子よりも優先順位が高いことがわかり*ます。したがって、関数宣言は次のようになります。

  • 識別子から開始:functionis

  • function() 引数を取らない関数

  • void* function()を返しますvoid*

この一般的な原則は、配列宣言([]もより優先順位が高い*)とその2つの組み合わせにも当てはまります。そう

int *(*arr[42])();

と読まれます

  • arr です
  • arr[42] 42要素の配列
  • *arr[42] へのポインタ
  • (*arr[42])() 引数を取らない関数と
  • int *(*arr[42])()を返しますint*

これに慣れるには少し時間がかかりますが、いったん原理を理解すれば、これらの宣言を明確に読むのは簡単です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.