Procurando entender os fundamentos de onde o termo " vazio " vem e por que ele é chamado de vazio. A intenção da pergunta é ajudar alguém que não tem experiência em C e, de repente, está olhando para uma base de código baseada em C.
Procurando entender os fundamentos de onde o termo " vazio " vem e por que ele é chamado de vazio. A intenção da pergunta é ajudar alguém que não tem experiência em C e, de repente, está olhando para uma base de código baseada em C.
Respostas:
Basicamente, significa "nada" ou "nenhum tipo"
Existem 3 maneiras básicas pelas quais o void é usado:
Argumento da função: int myFunc(void)
- a função não leva nada.
Valor de retorno da função: void myFunc(int)
- a função não retorna nada
Ponteiro de dados genérico: void* data
- 'data' é um ponteiro para dados de tipo desconhecido e não pode ser desreferenciado
Nota: o void
argumento em uma função é opcional em C ++, portanto, int myFunc()
é exatamente o mesmo que int myFunc(void)
e é deixado completamente de fora em C #. É sempre necessário para um valor de retorno.
Eu sempre entendi isso como ausente . Aqui estão quatro casos na linguagem C que os jogos para este uso do ausente
R f(void)
- Parâmetros de função ausentesvoid f(P)
- O valor de retorno está ausentevoid *p
- O tipo do que está apontado está ausente(void) p
- O uso do valor está ausenteOutros descendentes de C o usam para outras coisas. A D
linguagem de programação o utiliza para casos em que um inicializador está ausente
T t = void;
- valor inicial ausente(void)p
faz? Não entendi bem o que você quis dizer com "o uso de valor está ausente".
(void) var;
afirmação, encontrei respostas detalhadas em stackoverflow.com/q/21045615 .
Existem duas maneiras de usar o void:
void foo(void);
ou
void *bar(void*);
O primeiro indica que nenhum argumento está sendo passado ou que nenhum argumento está sendo retornado.
O segundo informa ao compilador que não há nenhum tipo associado aos dados, o que significa que você não pode usar os dados apontados até que sejam convertidos para um tipo conhecido.
Por exemplo, você verá void*
muito uso quando tiver uma interface que chame uma função cujos parâmetros não possam ser conhecidos antecipadamente.
Por exemplo, no Kernel do Linux ao adiar o trabalho, você configurará uma função para ser executada posteriormente, fornecendo um ponteiro para a função a ser executada e um ponteiro para os dados a serem passados para a função:
struct _deferred_work {
sruct list_head mylist;
.worker_func = bar;
.data = somedata;
} deferred_work;
Em seguida, um thread do kernel passa por uma lista de trabalhos adiados e, quando chega a este nó, efetivamente executa:
bar(somedata);
Então no bar você tem:
void bar(void* mydata) {
int *data = mydata;
/* do something with data */;
}
Significa "sem valor". Você usa void
para indicar que uma função não retorna um valor ou que não possui parâmetros ou ambos. Muito consistente com os usos típicos da palavra void em inglês.
Indica a ausência de um valor de retorno em uma função.
Alguns idiomas têm dois tipos de sub-rotinas: procedimentos e funções. Os procedimentos são apenas uma sequência de operações, enquanto uma função é uma sequência de operações que retornam um resultado.
Em C e seus derivados, a diferença entre os dois não é explícita. Tudo é basicamente uma função. a void
palavra - chave indica que não é uma função "real", pois não retorna um valor.
Pense no vazio como a "estrutura vazia". Deixe-me explicar.
Toda função usa uma sequência de parâmetros, onde cada parâmetro tem um tipo. De fato, podemos empacotar os parâmetros em uma estrutura, com os slots de estrutura correspondentes aos parâmetros. Isso faz com que cada função tenha exatamente um argumento. Da mesma forma, funções produzem um resultado, que tem um tipo. Pode ser um booleano, ou pode ser flutuante, ou pode ser uma estrutura, contendo um conjunto arbitrário de outros valores digitados. Se queremos um idioma que tenha vários valores de retorno, é fácil insistir que eles sejam empacotados em uma estrutura. De fato, sempre poderíamos insistir que uma função retornasse uma estrutura. Agora toda função usa exatamente um argumento e produz exatamente um valor.
Agora, o que acontece quando eu preciso de uma função que produza um valor "não"? Bem, considere o que recebo quando forme uma estrutura com 3 slots: ela contém 3 valores. Quando tenho 2 slots, ele contém dois valores. Quando tem um slot, um valor. E quando tem zero slots, ele mantém ... uh, valores zero ou "no" value ". Então, posso pensar em uma função retornando nula como retornando uma estrutura que não contém valores. Você pode até decidir que" nula " é apenas um sinônimo para o tipo representado pela estrutura vazia, em vez de uma palavra-chave no idioma (talvez seja apenas um tipo predefinido :)
Da mesma forma, posso pensar em uma função que não requer valores como aceitar uma estrutura vazia, por exemplo, "void".
Eu posso até implementar minha linguagem de programação dessa maneira. A passagem de um valor nulo ocupa zero bytes, portanto, a passagem de valores nulos é apenas um caso especial de transmissão de outros valores de tamanho arbitrário. Isso facilita para o compilador tratar o resultado ou argumento "nulo". Você provavelmente deseja um recurso de linguagem que possa jogar fora um resultado de função; em C, se você chamar a função de resultado não nulo foo na seguinte instrução: foo (...); o compilador sabe que foo produz um resultado e simplesmente o ignora. Se nulo é um valor, isso funciona perfeitamente e agora "procedimentos" (que são apenas um adjetivo para uma função com resultado nulo) são apenas casos especiais triviais de funções gerais.
Void * é um pouco mais engraçado. Eu não acho que os designers de C pensaram em vazio da maneira acima; eles apenas criaram uma palavra-chave. Essa palavra-chave estava disponível quando alguém precisava de um ponto para um tipo arbitrário, portanto nulo * como o idioma em C. Na verdade, funciona muito bem se você interpretar nulo como uma estrutura vazia. Um ponteiro nulo * é o endereço de um local onde essa estrutura vazia foi colocada.
As transmissões de void * para T * para outros tipos T também funcionam com essa perspectiva. As conversões de ponteiro são um truque completo que funciona nas arquiteturas mais comuns para aproveitar o fato de que, se um tipo de composto T tiver um elemento com o subtipo S colocado fisicamente no início de T em seu layout de armazenamento, então converter S * para T * e vice-versa, usando o mesmo endereço físico da máquina tende a dar certo, já que a maioria dos ponteiros de máquinas tem uma única representação. Substituir o tipo S pelo tipo vazio dá exatamente o mesmo efeito e, assim, a conversão de / para vazio * funciona.
A linguagem de programação PARLANSE implementa as idéias acima de perto. Fizemos uma brincadeira em seu design e não prestamos muita atenção a "void" como um tipo de retorno e, portanto, temos palavras-chave de idioma para procedimento. Principalmente é apenas uma simples mudança de sintaxe, mas é uma das coisas que você não consegue quando obtém um grande código de funcionamento do corpo em um idioma.
Em c #, você usaria a palavra-chave void para indicar que um método não retorna um valor:
public void DoSomeWork()
{
//some work
}
Três casos de uso para nulo:
Assinaturas de função. void foo(int bar)
não retorna um valor. int bar(void)
não tomar quaisquer parâmetros, mas isso geralmente é expressa com lista de argumentos vazio: int bar()
. O uso da palavra-chave void aqui corresponde ao seu significado em inglês.
Ponteiro genérico de tipo superior void *
que aponta para dados não especificados e não pode ser desreferenciado. Aqui, o significado de vazio é diferente de outros significados de vazio: tipo universal vs. nenhum tipo.
Em moldes que (void) new Foo(this)
significam que o valor de retorno é deliberadamente jogado fora. Aqui, o uso da palavra-chave também corresponde ao seu significado em inglês.
Os casos 1 e 2 já foram cobertos pelo @Gerald, mas o caso 3 ainda não foi abordado.
Se você está explicando o conceito a um iniciante, pode ser útil usar uma analogia. O uso de nulo em todos esses casos é análogo ao significado de uma página de um livro que possui as seguintes palavras: "Esta página foi deixada intencionalmente em branco". É diferenciar para o compilador entre algo que deve ser sinalizado como erro, versus um tipo que é intencionalmente deixado em branco porque esse é o comportamento que você deseja.
Ele sempre aparece no código em que normalmente você esperaria ver um tipo aparecer, como um tipo de retorno ou um tipo de ponteiro. É por isso que, em C #, void mapeia para um tipo CLR real, System.Void, porque é um tipo em si.
Algumas linguagens de programação nunca desenvolveram o conceito de vazio, assim como algumas culturas humanas nunca inventaram o conceito de número zero. Vazio representa o mesmo avanço em uma linguagem de programação que o conceito de zero representa para a linguagem humana.
Significa "sem valor". Você usa void para indicar que uma função não retorna um valor ou que não possui parâmetros ou ambos. É muito consistente com os usos típicos da palavra void em inglês.
Nulo não deve ser confundido com nulo. Nulo significa que para a variável cujo endereço está na pilha, o valor no heap para esse endereço está vazio.
Vazio é usado apenas em assinaturas de método. Para tipos de retorno, significa que o método não retornará nada ao código de chamada. Para parâmetros, significa que nenhum parâmetro é passado para o método
por exemplo
void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}
Em C #, podemos omitir o vazio para parâmetros e escrever o código acima como:
void MethodThatReturnsAndTakesVoid()
{
// Method body
}
Nulo não deve ser confundido com nulo. Nulo significa que para a variável cujo endereço está na pilha, o valor no heap para esse endereço está vazio.
void significa que você não retornará nenhum valor da função ou método
Anular significa nenhum valor necessário no tipo de retorno de uma função nos três idiomas.