Perché il tipo di vuoto di C non è analogo al tipo vuoto / inferiore?


28

Wikipedia e altre fonti che ho trovato elencano il voidtipo C come un tipo di unità anziché un tipo vuoto. Lo trovo confuso in quanto mi sembra che si voidadatti meglio alla definizione di un tipo vuoto / inferiore.

  • voidPer quanto ne so, non abitano valori .
  • Una funzione con un tipo restituito di vuoto specifica che la funzione non restituisce nulla e quindi può solo eseguire alcuni effetti collaterali.
  • Un puntatore di tipo void*è un sottotipo di tutti gli altri tipi di puntatore. Inoltre, le conversioni da e verso void*in C sono implicite.

Non sono sicuro se l'ultimo punto abbia qualche merito come argomento per voidessere un tipo vuoto, come void*è più o meno un caso speciale con poca relazione void.

D'altra parte, di per voidsé non è un sottotipo di tutti gli altri tipi, che per quanto ne so è un requisito per un tipo di essere un tipo di fondo.


10
Con "non restituisce nulla" si intende in realtà "non restituisce nulla di interessante", mentre una funzione con output vuoto non ritorna affatto (cioè si arresta in modo anomalo o si avvolge all'infinito).
Turion,

2
Come tipo di ritorno, void è un tipo di unità.
user253751

Risposte:


38

In C, voidè usato per più cose non correlate. A seconda di cosa viene utilizzato, il suo significato può essere un tipo di unità, un tipo vuoto o qualcos'altro.

Quando voidviene usato da solo (al contrario di void*un puntatore a vuoto), è un tipo di unità, cioè un tipo con un singolo valore. voidSi dice che le funzioni che restituiscono "non restituiscono nulla", ma ciò che significa in realtà è che non restituiscono alcuna informazione. Restituiscono bit di informazioni, il che significa che restituiscono un valore di un tipo che contiene valori distinti, ovvero un tipo di unità.2 0 = 1020=1

Questo non è un tipo vuoto: una funzione che restituisce un tipo vuoto non può restituire un valore, poiché non esiste un valore di quel tipo. Una funzione il cui tipo di ritorno è vuoto può solo essere ripetuta in loop per sempre, oppure interrompere il programma o sollevare un'eccezione ( longjmp) (o altrimenti organizzare il non ritorno, ad esempio trasferendo il controllo su un altro thread o processo utilizzando funzionalità oltre lo standard C). Per confondere le cose, è convenzionale in C usare voidal posto di un tipo vuoto (C non ha un tipo vuoto).

Il voidtipo richiede bit di memoria. Poiché C insiste su ogni oggetto che occupa un numero intero, diverso da zero di byte di memoria, è vietato creare un oggetto di tipo e c'è una sintassi speciale per restituire il valore ( un'istruzione con il valore omesso). Non c'è sintassi che dia il valore di tipo , ma quel valore è presente ogni volta che una funzione il cui tipo di ritorno è restituito.0voidvoidreturnvoidvoid

C non ha un tipo di fondo nel senso di consentire qualsiasi tipo possibile. Anche i tipi incompleti specificano la natura generale dei suoi valori, ad esempio puntatori o strutture o unioni o funzioni. Ma void*è un puntatore a qualsiasi tipo di non funzione: è il minimo elemento dell'algebra dei tipi di puntatore oggetto, ovvero è il tipo di puntatore oggetto in basso. A differenza del caso generale in T*cui Tesiste un tipo non vuoto, void*non è il tipo di puntatori a un valore di tipo void, ma il tipo di puntatori a un valore di tipo non specificato.


Si può restituire il vuoto in C ++ e C89. stackoverflow.com/questions/35987493/...
BartekChom

2
Il quarto paragrafo è formalmente sbagliato. In C, la quantità di memoria per voidè indefinita, non zero. Questo non è il motivo per cui gli oggetti di tipo voidnon sono consentiti. Il motivo formale è che voidè un tipo incompleto e gli oggetti non possono avere un tipo incompleto.
Salterio

4
@MSalters No, quello che ho scritto è formalmente corretto. "Perché" si riferisce alla motivazione per la progettazione del linguaggio, non alle inferenze logiche all'interno delle specifiche del linguaggio. Il voidtipo richiede 0 bit di memoria. Questo è il motivo per cui i progettisti di C hanno deciso di creare voidun tipo incompleto, invece di definirlo prendendo 0 byte di memoria (che avrebbe un grande impatto sul design del linguaggio) o 1 byte di memoria (che avrebbe sprecato spazio) .
Gilles 'SO- smetti di essere malvagio' il

1
@Gilles: Mi dispiace, ma neanche questo ha senso. Se consentito, lo spazio utilizzato sarebbe 1 byte per oggetto di tipo vuoto e ovviamente non sono necessari molti oggetti di voidtipo. Per non parlare del fatto che questi oggetti potrebbero alias tutti gli altri oggetti, quindi l'utilizzo effettivo sarebbe comunque zero.
Salterio

4
@CodesInChaos: Bene, C ++ in realtà consente strutture vuote, ad es struct E { };. Se utilizzato come classe di base, può essere di dimensioni zero. (Non esiste davvero nulla come C / C ++, le due lingue fanno le proprie scelte e possono differire in queste aree. C ovviamente non ha classi di base vuote, in quanto non ha OO in primo luogo)
MSalters

11

Il nome "tipo vuoto" è forse confuso. Ciò significa che, come dici tu stesso, il tipo non contiene valori . Il "vuoto" non si riferisce a nessun singolo valore del tipo, si riferisce al tipo nel suo insieme, considerato come ~ un insieme di possibili valori. Quindi questo non dice qualcosa come "una funzione che voidritorna non restituisce informazioni", ma "non esiste alcun valore di tipo ".

Ciò significa che una funzione il cui tipo di risultato è non può mai terminare. Se è terminato, se dovrebbe restituire un valore di , ma, beh, tale valore non esiste.

Significa anche che non è nemmeno possibile discutere quante informazioni contenga un valore di tipo vuoto, perché non esiste tale valore. (O se vuoi, un'affermazione senza senso come "qualsiasi valore di tipo vuoto contiene esattamente 35093658 bit di informazioni" è vagamente vera.) È piuttosto utile (anche se non proprio corretto) pensare ai valori come contenenti una quantità infinita di informazioni.

Considerando che una funzione C con "tipo restituito" puòvoid chiaramente restituire, ma non fornisce alcuna informazione nel suo valore di ritorno. Bene, questo è esattamente ciò che caratterizza un tipo di unità: i suoi valori non contengono alcuna informazione, perché esiste solo uno di questi valori (quindi puoi sempre dire quale sarà il valore restituito, anche senza preoccuparti di chiamare mai la funzione).

Per citare Conor McBride (traslitterato in C):

voidsignifica "noioso". Significa il tipo noioso che contiene una cosa, anche noioso. Non c'è nulla di interessante da guadagnare confrontando un elemento del tipo noioso con un altro, perché non c'è nulla da imparare su un elemento del tipo noioso, dandogli la tua attenzione.

È molto diverso dal tipo vuoto [...]. Il tipo vuoto è molto eccitante, perché se qualcuno ti dà mai un valore che gli appartiene, sai che sei già morto e in Paradiso e che tutto ciò che vuoi è tuo.


Interessante; se la definizione di ⊥ è la funzione il cui tipo di ritorno è ⊥ non può mai terminare, allora C ha un tale tipo. Lo chiamiamo vuoto volatile.
Giosuè,

Interessante, non lo sapevo. Tuttavia, non sembra essere conforme agli standard .
leftaroundabout
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.