Cのvoid型がempty / bottom型と類似していないのはなぜですか?


28

ウィキペディアと私が見つけた他のソースはvoid、空のタイプではなくユニットタイプとしてリストCのタイプを見つけました。void空の/下の型の定義によりよく適合するように思えるので、この混乱を見つけます。

  • void私が知る限り、値は存在しません。
  • 戻り値の型がvoidの関数は、関数が何も返さないため、何らかの副作用しか実行できないことを指定します。
  • タイプのポインターvoid*は、他のすべてのポインタータイプのサブタイプです。また、void*C との間の変換は暗黙的です。

最後の点voidに、空の型であることの引数としてのメリットがあるかどうかはわかりvoid*ませんvoid

一方、voidそれ自体は他のすべてのタイプのサブタイプではありません。これは、タイプがボトムタイプであるための要件であると言えます。


10
「何も返さない」とは、実際には「重要なものを返さない」という意味ですが、出力が空の関数はまったく返されません(つまり、クラッシュまたは無限ループ)。
チュリオン

2
戻り型として、voidはユニット型です。
user253751

回答:


38

Cでは、void複数の無関係なものに使用されます。使用目的に応じて、その意味はユニットタイプ、空のタイプ、または他の何かになります。

voidが(void*void とは対照的に)単独で使用される場合、それはユニット型、つまり単一の値を持つ型です。返さvoidれる関数は「何も返さない」と言われますが、これが本当に意味するのは、情報を返さないことです。これらはビットの情報を返します。つまり、2 0 = 1の異なる値を含む型の値、つまりユニット型を返します。020=1

これは空のタイプではありません。空のタイプを返す関数は、そのタイプの値がないため、値を返すことはできません。戻り値の型が空の関数は、永久にループするか、プログラムを中止するか、例外(longjmp)を発生させます(または、標準Cを超える機能を使用して別のスレッドまたはプロセスに制御を移すなどして戻りません)。混乱を避けるために、voidCでは空の型の代わりに使用するのが一般的です(Cには空の型はありません)。

このvoidタイプにはビットのストレージが必要です。Cはすべてのオブジェクトがゼロ以外のストレージバイト全体を占有しているため、typeのオブジェクトを作成することは禁じられており、値(値が省略されたステートメント)を返す特別な構文があります。typeの値を生成する構文はありませんが、戻り値の型が関数から返されるたびにその値が存在します。0voidvoidreturnvoidvoid

Cには、可能な型を許可するという意味で、ボトム型がありません。不完全な型でさえ、その値の一般的な性質、たとえばポインターや構造体、共用体、関数を指定します。しかしvoid*、非関数型へのポインターです。これはオブジェクトポインター型の代数の最小要素です。つまり、一番下のオブジェクトポインター型です。T*where Tが非void型である一般的な場合とは異なり、void*typeの値へのポインターの型ではなく、void未指定の型の値へのポインターの型です。


C ++およびC89ではvoidを返すことができます。stackoverflow.com/questions/35987493/…–
BartekChom

2
4番目の段落は正式に間違っています。Cでは、ストレージの量はvoidゼロではなく未定義です。これは、型のオブジェクトvoidが許可されない理由ではありません。正式な理由は、それvoid不完全な型であり、オブジェクトが不完全な型を持つことはできないということです。
–MSalters

4
@MSaltersいいえ、私が書いたものは正式に正しいものです。「理由」とは、言語仕様内の論理的な推論ではなく、言語設計の動機を指します。このvoidタイプに 0ビットのストレージが必要です。これが、Cの設計者がvoid、0バイトのストレージ(言語設計に大きな影響を与える)または1バイトのストレージ(スペースを浪費する)を取ると定義するのではなく、不完全なタイプを作成することにした理由です。。
ジル 'SO-悪であるのをやめる'

1
@Gilles:申し訳ありませんが、それも意味がありません。許可されている場合、使用されるスペースはvoid型のオブジェクトごとに1バイトになり、明らかに多くのvoid型のオブジェクトは必要ありません。これらのオブジェクトが他のすべてのオブジェクトをエイリアスできることは言うまでもないので、実際の使用量はとにかくゼロになります。
–MSalters

4
@CodesInChaos:まあ、C ++は実際には空の構造体、つまりを許可しますstruct E { };。基本クラスとして使用する場合、これはゼロサイズにすることができます。(C / C ++のようなものは本当にありません、二つの言語が自分の選択をすると、彼らはこれらの分野で異なること、それは最初の場所でOOを持っていないとして、Cは明らかに、空の基底クラスを持っていません。)
MSaltersは、

11

「空のタイプ」という名前は紛らわしいかもしれません。これが意味することは、あなたが自分で言うように、型には値が含まれていないということです。「空」とは、その型の個々の値を指すのではなく、可能な値のセットと見なされる型全体を指します。そのため、これは「返す関数が情報を返さない」などのことを言っているのでvoidはなく、「型の値が存在しない」ということです。

これは、その結果タイプである機能を意味することができます決して終了しませんが。終了した場合、値を返さなければならない場合、そのような値は存在しません。

また、空の型の値に含まれる情報の量を議論することさえできないということです。なぜなら、そのような値はないからです。(または、「空の型の値には正確に35093658ビットの情報が含まれる」などの無意味な文は空虚に真実です。)値を無限の情報を含むと考えるのは多少役立ちます(実際には正しくありません)。

「戻り値の型」を持つC関数のに対しvoid明確にすることができ返しますが、あなたは、その戻り値のいずれかの情報を与えるものではありません。まあ、それはまさにユニットタイプの特徴です:そのような値は1つしかないため、その値には情報が含まれていません(したがって、関数を呼び出さなくても戻り値が何であるかを常に言うことができます)。

Conor McBrideを引用するには(Cに音訳):

void「退屈」を意味します。これは、1つのことも退屈でもある退屈なタイプを意味します。退屈なタイプの要素を他の要素と比較することによって得られる興味深いものはありません。なぜなら、退屈なタイプの要素に注意を向けることによって学ぶことは何もないからです。

空のタイプとは非常に異なります[...]。空のタイプは非常にエキサイティングです。誰かがあなたにそれに値を与えれば、あなたはすでに死んでいて天国にいること、そしてあなたが望むものはあなたのものだということを知っているからです。


面白い; ⊥の定義が、戻り値の型がisである関数で終了できない場合、Cにはそのような型があります。これをvolatile voidと呼びます。
ジョシュア

興味深いことに、私はそれを知りませんでした。ただし、実際には標準に準拠していないようです。
左辺り
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.