C、C ++、C#でvoidとはどういう意味ですか?


170

void」という用語がどこから来たのか、なぜそれがvoidと呼ばれるのかについての基本を理解する。この質問の意図は、Cの経験がなく、突然Cベースのコードベースを調べている人を支援することです。


2
この質問は3つの言語を組み合わせています...そのレガシーの質問は3つの異なる質問に分割する必要があります。
Stargateur

回答:


225

基本的には「何もない」または「タイプなし」を意味します

voidが使用される3つの基本的な方法があります。

  1. 関数の引数:int myFunc(void) -関数は何も取りません。

  2. 関数の戻り値:void myFunc(int) -関数は何も返しません

  3. ジェネリックデータポインター:void* data -'data'は不明なタイプのデータへのポインターであり、逆参照できません

注:voidin関数の引数はC ++ではオプションであるため、int myFunc()とまったく同じでint myFunc(void)、C#では完全に省略されます。戻り値には常に必要です。


7
引数リスト内のボイドは、C ++で任意であり、参照stackoverflow.com/questions/416345/...
ダニエルエリカー

1
「サイズなし」ではなく「タイプなし」を使用する
Kjetil Joergensen

@Earwickerとkjetijor、どちらも私が議論した良い点ですが、私の眠れない心には助けが必要でした;)ありがとう。
ジェラルド

9
意見の相違はありませんが、「キャストトゥヴォイド」のトリックでは、未使用の値に対する警告を抑制するためにvoidをさらに使用しています。コンパイラーによる解釈に実際には対応していないため、少し伸びていますが、「この値を使用して何もしない」という意味で解釈できます。
スティーブジェソップ

22
C ++では、引数リストのvoidはオプションです。ただし、Cでは、これはオプションではありません。foo()は、任意のタイプの任意の数のパラメーターを取ることを意味しますが、foo(void)は、パラメーターを取ることを意味します。
Adam Rosenfield、

33

私はいつもそれが不在を意味すると考えてきました。この不在の使用に一致するC言語の4つのケースを次に示します。

  • R f(void)-関数パラメーターがありません
  • void f(P)-戻り値がありません
  • void *p-指されているもののタイプはありません
  • (void) p-値の使用はありません

他のCの子孫はそれを他のものに使用します。Dプログラミング言語は初期化子がある場合に使用します欠席

  • T t = void;-初期化値がありません

4
何をし(void)pますか?「価値の使い方はない」というあなたの意味がよくわかりませんでした。
Yashas 2017年

誰も混乱している場合@Yashas (void) var;声明、私はで詳細な回答を見つけたstackoverflow.com/q/21045615
Arnie97

14

voidを使用するには2つの方法があります。

void foo(void);

または

void *bar(void*);

1つ目は、引数が渡されていないか、引数が返されていないことを示しています。

2番目は、データに関連付けられている型がないことをコンパイラーに伝えます。つまり、既知の型にキャストされるまで、ポイントされたデータを使用できないことを意味します。

たとえば、void*事前にパラメータを知ることができない関数を呼び出すインターフェイスがある場合、よく使用されます。

たとえば、Linuxカーネルでは、作業を延期するときに、実行する関数へのポインターと関数に渡されるデータへのポインターを指定して、後で実行する関数を設定します。

struct _deferred_work {
sruct list_head mylist;
.worker_func = bar;
.data        = somedata;
} deferred_work;

次に、カーネルスレッドは延期された作業のリストを調べ、このノードに到達すると、効果的に実行されます。

bar(somedata);

次に、あなたはバーにいます:

void bar(void* mydata) {
    int *data = mydata;
    /* do something with data */;
}

13

「価値なし」を意味します。void関数が値を返さないか、関数にパラメータがないか、またはその両方があることを示すために使用します。英語のvoidという単語の典型的な使用法とほぼ一致しています。


4

関数に戻り値がないことを示します。

一部の言語には、プロシージャと関数の2種類のサブルーチンがあります。プロシージャは単なる一連の操作ですが、関数は結果を返す一連の操作です。

Cとその派生物では、2つの違いは明確ではありません。すべては基本的に関数です。voidキーワードは、それが値を返さないので、それは、「実際の」機能ではないということを示しています。


3

voidを「空の構造」と考えてください。説明させてください。

すべての関数は一連のパラメーターを受け取り、各パラメーターにはタイプがあります。実際、パラメータに対応する構造スロットを使用して、パラメータを構造にパッケージ化できます。これにより、すべての関数が引数を1つだけ持つようになります。同様に、関数はタイプを持つ結果を生成します。これはブール値でも、浮動小数点数でも、他の型付き値の任意のセットを含む構造でもかまいません。複数の戻り値を持つ言語が必要な場合は、それらが構造体にパッケージ化されていると主張するのは簡単です。実際、関数が構造体を返すことを常に主張することができました。これで、すべての関数が1つの引数を取り、1つの値を生成します。

さて、 "no"値を生成する関数が必要な場合はどうなりますか?ええと、3つのスロットを持つ構造体を形成したときに何が得られるかを考えてみましょう。2つのスロットがある場合、2つの値を保持します。スロットが1つの場合、値は1つです。そして、それがスロットを持たないとき、それは保持します...ええと、ゼロの値、または「no」の値です。したがって、voidを返す関数は、値を含まない構造体を返すものと考えることができます。言語のキーワードではなく、空の構造体で表される型の同義語です(おそらく事前定義された型だけかもしれません)。

同様に、値を必要としない関数は、「void」などの空の構造を受け入れるものと考えることができます。

この方法でプログラミング言語を実装することもできます。void値を渡すことは0バイトを占めるため、void値を渡すことは、任意のサイズの他の値を渡す特別な場合にすぎません。これにより、コンパイラは「void」の結果または引数を簡単に処理できます。おそらく、関数の結果を破棄できる言語機能が必要です。Cでは、次のステートメントで非void結果関数fooを呼び出す場合:foo(...); コンパイラーは、fooが結果を生成することを認識し、単にそれを無視します。voidが値である場合、これは完全に機能し、「手続き」(これはvoid結果を伴う関数の単なる形容詞です)は、一般的な関数のほんのささいな特殊ケースです。

Void *は少しおかしいです。Cの設計者が上記の方法で無効を考えたとは思いません。彼らはちょうどキーワードを作成しました。そのキーワードは、誰かが任意の型へのポイントを必要とするときに使用できたため、Cのイディオムとしてvoid *になります。voidを空の構造体として解釈すると、実際には非常にうまく機能します。void *ポインターは、その空の構造が置かれた場所のアドレスです。

他の型Tのvoid *からT *へのキャストも、この観点で機能します。ポインターキャストは完全なチートであり、複合型TにサブタイプSの要素がストレージレイアウトのTの先頭に物理的に配置されている場合、S *をT *にキャストし、ほとんどのマシンポインターは単一の表現を持っているため、同じ物理マシンアドレスを使用すると、逆にうまくいく傾向があります。タイプSをタイプvoidに置き換えると、まったく同じ効果が得られるため、void *とのキャストが機能します。

PARLANSEプログラミング言語は、上記のアイデアをかなり密接に実装しています。私たちはその設計に失敗し、戻り型としての「void」に細心の注意を払わなかったため、プロシージャの言語キーワードがありました。そのほとんどは単純な構文の変更ですが、言語で大きな本体動作コードを取得すると、回避できないことの1つです。



2

voidの3つの使用例:

  1. 関数のシグネチャ。void foo(int bar)値を返しません。int bar(void)はパラメータを取りませんが、通常は空の引数リストで表現されます:int bar()。ここでのvoidキーワードの使用は、英語でのその意味に対応しています。

  2. void *未指定のデータを指し、逆参照できない汎用トップタイプポインター。ここで、voidの意味は、他のvoidの意味とは異なります。ユニバーサルタイプとタイプなし。

  3. などのキャスト(void) new Foo(this)では、戻り値が意図的に破棄されていることを示します。ここで、キーワードの使用法は英語での意味にも一致します。

ケース1と2はすでに@Geraldでカバーされていますが、ケース3はまだ対処されていません。


2

概念を初心者に説明する場合は、類推を使用すると役立つ場合があります。これらすべてのケースでvoidを使用することは、「このページは意図的に空白にされています」という単語が含まれている本のページと同じ意味です。これは、エラーとしてフラグを立てるべきものと、意図的に空白のままにしておくべき型とをコンパイラが区別するためのものです。

これは常に、戻り型やポインタ型など、通常は型が表示されると予想されるコードに表示されます。これがC#では、voidがそれ自体が型であるため、実際のCLR型であるSystem.Voidにマップされる理由です。

一部のプログラミング言語は、いくつかの人間の文化がゼロという概念を発明したことがないように、ボイドの概念を開発しませんでした。Voidは、ゼロの概念が人間の言語を表すのと同じ、プログラミング言語の進歩を表します。


あなたの最後の文に関する注意点-静的に型付けされた言語にのみ当てはまることを覚えておいてください。動的に型付けされた言語は、メソッドが単に何も返さない可能性があるため、voidを必要としません。「void」は、他に何も返されないことを意味します。
Mark

私の最後のコメントへの訂正-私は最後の段落を(文章ではなく)言うつもりでした。
Mark Embling、

1

「価値なし」を意味します。voidを使用して、関数が値を返さないか、パラメーターがないか、またはその両方であることを示します。英語でのvoidという単語の一般的な使用とよく一致しています。

Voidをnullと混同しないでください。Nullは、アドレスがスタックにある変数の場合、そのアドレスのヒープ上の値が空であることを意味します。


0

Voidはメソッドシグネチャでのみ使用されます。戻り値の型の場合、メソッドが呼び出しコードに何も返さないことを意味します。パラメータの場合、メソッドにパラメータが渡されないことを意味します

例えば

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

C#では、パラメーターのvoidを省略して、上記のコードを次のように記述できます。

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

Voidをnullと混同しないでください。Nullは、アドレスがスタックにある変数の場合、そのアドレスのヒープ上の値が空であることを意味します。


0

Voidは、定義上、左辺値にはならない不完全な型です。つまり、値を割り当てることができません。

したがって、値を保持することもできません。




-1

VoidはVisual BasicのSubに相当します。


戻り型としてのみ。voidのさらに3つの使用法を考えることができます:void引数(関数は何も取りません)、voidポインター(ポインタータイプが指定されていません)、およびvoidキャスト(値を破棄)。
c4757p 2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.