Por que o tipo de vácuo de C não é análogo ao tipo vazio / inferior?

28

A Wikipedia e outras fontes que eu encontrei listam o voidtipo de C como um tipo de unidade, em vez de um tipo vazio. Acho isso confuso, pois me parece que voidmelhor se ajusta à definição de um tipo vazio / inferior.

  • Nenhum valor habita void, até onde eu sei.
  • Uma função com um tipo de retorno de nulo especifica que a função não retorna nada e, portanto, só pode executar algum efeito colateral.
  • Um ponteiro do tipo void*é um subtipo de todos os outros tipos de ponteiros. Além disso, as conversões de e void*para C estão implícitas.

Não tenho certeza se o último ponto tem algum mérito como argumento por voidser do tipo vazio, como void*é mais ou menos um caso especial com pouca relação com void.

Por outro lado, voidele próprio não é um subtipo de todos os outros tipos, o que, até onde eu sei, é um requisito para que um tipo seja do tipo inferior.

Meta
fonte
10
Por "não retorna nada", na verdade você quer dizer "não retorna nada de interesse", enquanto uma função com saída vazia não retorna absolutamente (ou seja, trava ou faz loops infinitamente).
Turion
2
Como um tipo de retorno, nulo é um tipo de unidade.
user253751

Respostas:

38

Em C, voidé usado para várias coisas não relacionadas. Dependendo do uso, seu significado pode ser um tipo de unidade, um tipo vazio ou qualquer outra coisa.

Quando voidé usado por si só (ao contrário de void*um ponteiro para anular), é um tipo de unidade, ou seja, um tipo com um único valor. voidDiz-se que as funções que retornam "não retornam nada", mas o que isso realmente significa é que elas não retornam nenhuma informação. Eles retornam bits de informação, o que significa que retornam um valor de um tipo que contém valores distintos, ou seja, um tipo de unidade.2 0 = 1020=1

Este não é um tipo vazio: uma função que retorna um tipo vazio não pode retornar um valor, pois não há valor desse tipo. Uma função cujo tipo de retorno está vazio pode fazer loop apenas para sempre, ou abortar o programa, ou gerar uma exceção ( longjmp) (ou de outra forma organizar para não retornar, por exemplo, transferindo o controle para outro thread ou processo usando a funcionalidade além do padrão C). Para manter as coisas confusas, é convencional em C usar voidno lugar de um tipo vazio (C não tem um tipo vazio).

O voidtipo requer bits de armazenamento. Como C insiste em todos os objetos que ocupam um número inteiro e nulo de bytes de armazenamento, é proibido criar um objeto do tipo e há uma sintaxe especial para retornar o valor (uma declaração com o valor omitido). Não há sintaxe que produz o valor do tipo , mas esse valor existe sempre que uma função cujo tipo de retorno é retornado.0voidvoidreturnvoidvoid

C não possui um tipo inferior no sentido de permitir qualquer tipo possível. Mesmo tipos incompletos especificam a natureza geral de seus valores, por exemplo, ponteiros ou estruturas, uniões ou funções. Mas void*é um ponteiro para qualquer tipo que não seja de função: é o menor elemento da álgebra dos tipos de ponteiros de objetos, ou seja, é o tipo de ponteiro de objeto inferior. Ao contrário do caso geral de T*onde Té algum tipo não nulo, void*não é o tipo de ponteiros para um valor do tipo void, mas o tipo de ponteiros para um valor do tipo não especificado.

Gilles 'SO- parar de ser mau'
fonte
Pode-se retornar nulo em C ++ e C89. stackoverflow.com/questions/35987493/…
BartekChom 7/16
2
O quarto parágrafo está formalmente errado. Em C, a quantidade de armazenamento para voidé indefinida, não zero. Esta não é a razão pela qual objetos do tipo voidnão são permitidos. A razão formal é que esse voidé um tipo incompleto e os objetos não podem ter um tipo incompleto.
MSalters
4
@MSalters Não, o que escrevi está formalmente correto. "Porque" refere-se à motivação para o design da linguagem, não às inferências lógicas dentro da especificação da linguagem. O voidtipo requer 0 bits de armazenamento. Essa é a razão pela qual os designers de C decidiram criar voidum tipo incompleto, em vez de defini-lo usando 0 bytes de armazenamento (o que teria muito impacto no design da linguagem) ou 1 byte de armazenamento (o que desperdiçaria espaço) .
Gilles 'SO- stop be evil'
11
@ Gilles: Desculpe, mas isso também não faz sentido. Se permitido, o espaço usado seria 1 byte por objeto do tipo void , e você obviamente não precisará de muitos objetos do voidtipo. Sem mencionar que esses objetos poderiam alias todos os outros objetos, portanto o uso real seria zero de qualquer maneira.
MSalters
4
@CodesInChaos: Bem, C ++ realmente permite estruturas vazias, ou seja struct E { };. Quando usado como uma classe base, isso pode ser de tamanho zero. (Não existe realmente C / C ++, as duas linguagens fazem suas próprias escolhas e podem diferir nessas áreas. C obviamente não possui classes base vazias, pois não possui OO em primeiro lugar)
MSalters
11

O nome "tipo vazio" talvez seja confuso. O que isso significa é que, como você diz, o tipo não contém valores . O "vazio" não se refere a nenhum valor individual do tipo, refere-se ao tipo como um todo, considerado como um conjunto de valores possíveis. Portanto, isso não diz algo como "uma função retornando voidnão retorna informações", mas "não existe valor do tipo ".

Isso significa que uma função cujo tipo de resultado é nunca pode terminar. Se ele terminou, se precisaria retornar um valor de , mas, bem, esse valor não existe.

Também significa que não é possível discutir quanta informação um valor do tipo vazio conteria, porque não existe esse valor. (Ou, se preferir, uma declaração sem sentido como "qualquer valor do tipo vazio contém exatamente 35093658 bits de informação" é vacuamente verdadeira.) É um pouco útil (embora não seja realmente correto) pensar em valores como contendo uma quantidade infinita de informações.

Enquanto uma função C com "tipo de retorno" voidclaramente pode retornar, mas não fornece nenhuma informação em seu valor de retorno. Bem, é exatamente isso que caracteriza um tipo de unidade: seus valores não contêm nenhuma informação, porque existe apenas um valor (portanto, você sempre pode dizer qual será o valor de retorno, mesmo sem se preocupar em chamar a função).

Para citar Conor McBride (transliterado para C):

voidsignifica "chato". Significa o tipo chato que contém uma coisa, também chata. Não há nada de interessante a ganhar comparando um elemento do tipo chato com outro, porque não há nada a aprender sobre um elemento do tipo chato, dando-lhe alguma atenção.

É muito diferente do tipo vazio [...]. O tipo vazio é muito empolgante, porque se alguém lhe der um valor pertencente a ele, você saberá que já está morto e está no céu e que tudo o que deseja é seu.

leftaroundabout
fonte
Interessante; se a definição de ⊥ é a função cujo tipo de retorno é ⊥ nunca pode terminar, então C possui esse tipo. Chamamos isso de vazio volátil.
Joshua Joshua
Interessante, eu não sabia disso. Porém, eu não pareço estar em conformidade com os padrões .
precisa saber é o seguinte