Co oznacza void w językach C, C ++ i C #?


170

Chcielibyśmy poznać podstawy dotyczące tego, skąd pochodzi termin „ pustka ” i dlaczego nazywa się go pustką. Celem pytania jest pomoc komuś, kto nie ma doświadczenia w C i nagle szuka kodu opartego na C.


2
To pytanie łączy 3 języki ... to starsze pytanie należy podzielić na 3 różne pytania.
Stargateur

Odpowiedzi:


225

Zasadniczo oznacza „nic” lub „brak typu”

Istnieją 3 podstawowe sposoby wykorzystania void:

  1. Argument funkcji: int myFunc(void) - funkcja nic nie pobiera.

  2. Wartość zwracana funkcji: void myFunc(int) - funkcja nic nie zwraca

  3. Ogólny wskaźnik danych: void* data - „dane” to wskaźnik do danych nieznanego typu, którego nie można wyłuskać

Uwaga: voidargument in a function jest opcjonalny w C ++, więc int myFunc()jest dokładnie taki sam jak int myFunc(void)i jest całkowicie pomijany w C #. Jest to zawsze wymagane dla wartości zwracanej.


7
void na liście argumentów jest opcjonalne w C ++, patrz stackoverflow.com/questions/416345/…
Daniel Earwicker


@Earwicker i kjetijor, oba dobre punkty, nad którymi debatowałem, ale mój bezsenny umysł potrzebował pomocy;) Dzięki.
Gerald

9
Nie zgadzam się, ale dodatkowe użycie void jest w sztuczce „rzut na próżnię”, która ma na celu stłumienie ostrzeżeń dla nieużywanych wartości. To trochę naciągane, ponieważ tak naprawdę nie odpowiada temu, jak kompilator interpretuje rzeczy, ale możesz zinterpretować to jako „Używam tej wartości, aby nic nie robić”.
Steve Jessop,

22
W C ++ void na liście argumentów jest opcjonalne. Jednak w C NIE jest opcjonalne: foo () oznacza, że ​​przyjmuje dowolną liczbę parametrów dowolnego typu, podczas gdy foo (void) oznacza, że ​​przyjmuje zero parametrów.
Adam Rosenfield

33

Zawsze uważałem, że oznacza nieobecność . Oto cztery przypadki w języku C, które pasują do tego zastosowania nieobecności

  • R f(void)- parametry funkcyjne są nieobecne
  • void f(P)- Brak wartości zwracanej
  • void *p- Rodzaj co jest wskazywany jest nieobecny
  • (void) p- Wykorzystanie wartości jest nieobecny

Inni potomkowie C używają go do innych celów. Język Dprogramowania używa go w przypadkach, gdy nie ma inicjatora

  • T t = void;- brak wartości inicjalizacyjnej

4
Co robi (void)p? Nie do końca rozumiem, co masz na myśli, mówiąc „brak użycia wartości”.
Yashas

@Yashas Jeśli ktoś jest również zdezorientowany co do tego (void) var;stwierdzenia, szczegółowe odpowiedzi znalazłem na stackoverflow.com/q/21045615 .
Arnie97

14

Istnieją dwa sposoby korzystania z void:

void foo(void);

lub

void *bar(void*);

Pierwsza wskazuje, że żaden argument nie jest przekazywany lub nie jest zwracany żaden argument.

Druga mówi kompilatorowi, że nie ma typu związanego z danymi, co oznacza, że ​​nie można użyć wskazanych danych, dopóki nie zostaną one rzutowane na znany typ.

Na przykład zobaczysz void*często używane, gdy masz interfejs, który wywołuje funkcję, której parametry nie mogą być znane z wyprzedzeniem.

Na przykład w jądrze Linuksa podczas odroczenia pracy skonfigurujesz funkcję do uruchomienia w późniejszym czasie, dając jej wskaźnik do funkcji, która ma być uruchomiona i wskaźnik do danych, które mają być przekazane do funkcji:

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

Następnie wątek jądra przegląda listę odroczonej pracy i kiedy dotrze do tego węzła, skutecznie wykonuje:

bar(somedata);

W barze masz:

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

13

To znaczy „brak wartości”. Służy voiddo wskazania, że ​​funkcja nie zwraca wartości lub że nie ma parametrów lub obie te wartości. Prawie zgodne z typowymi zastosowaniami słowa void w języku angielskim.


4

Wskazuje na brak wartości zwracanej w funkcji.

Niektóre języki mają dwa rodzaje podprogramów: procedury i funkcje. Procedury to tylko sekwencja operacji, podczas gdy funkcja to sekwencja operacji, które zwracają wynik.

W C i jego pochodnych różnica między nimi nie jest wyraźna. W zasadzie wszystko jest funkcją. voidsłów kluczowych wskazuje, że to nie jest „rzeczywisty” funkcja, ponieważ nie zwraca wartości.


3

Pomyśl o pustce jako o „pustej strukturze”. Pozwól mi wyjaśnić.

Każda funkcja przyjmuje sekwencję parametrów, przy czym każdy parametr ma typ. W rzeczywistości moglibyśmy spakować parametry w strukturę, w której szczeliny struktury odpowiadają parametrom. To sprawia, że ​​każda funkcja ma dokładnie jeden argument. Podobnie funkcje dają wynik, który ma typ. Może to być wartość logiczna, zmiennoprzecinkowa lub struktura zawierająca dowolny zestaw innych wpisanych wartości. Jeśli chcemy języka, który ma wiele zwracanych wartości, łatwo jest po prostu nalegać, aby były one spakowane w strukturę. W rzeczywistości zawsze moglibyśmy nalegać, aby funkcja zwracała strukturę. Teraz każda funkcja przyjmuje dokładnie jeden argument i generuje dokładnie jedną wartość.

Co się dzieje, gdy potrzebuję funkcji, która generuje wartość „nie”? Cóż, zastanów się, co otrzymuję, gdy utworzę strukturę z 3 gniazdami: zawiera 3 wartości. Kiedy mam 2 gniazda, ma dwie wartości. Gdy ma jeden slot, jedną wartość. A kiedy ma zerowe szczeliny, przechowuje ... uh, zerowe wartości lub „brak”. Tak więc mogę myśleć o funkcji zwracającej void jako zwracającej strukturę nie zawierającą wartości. Możesz nawet zdecydować, że „void” jest tylko synonimem typu reprezentowanego przez pustą strukturę, a nie słowem kluczowym w języku (może to tylko predefiniowany typ :)

Podobnie, mogę myśleć o funkcji nie wymagającej wartości jako akceptującej pustą strukturę, np. „Void”.

Mogę nawet w ten sposób zaimplementować swój język programowania. Przekazanie wartości void zajmuje zero bajtów, więc przekazywanie wartości void jest tylko specjalnym przypadkiem przekazywania innych wartości o dowolnym rozmiarze. Ułatwia to kompilatorowi traktowanie wyniku lub argumentu „void”. Prawdopodobnie potrzebujesz funkcji langauge, która może odrzucać wynik funkcji; w C, jeśli wywołasz funkcję wynikową nieważną foo w następującej instrukcji: foo (...); kompilator wie, że foo daje wynik i po prostu go ignoruje. Jeśli void jest wartością, działa to doskonale, a teraz „procedury” (które są po prostu przymiotnikiem funkcji z wynikiem void) są po prostu trywialnymi przypadkami specjalnymi funkcji ogólnych.

Void * jest trochę zabawniejszy. Nie sądzę, by projektanci C myśleli o pustce w powyższy sposób; po prostu utworzyli słowo kluczowe. To słowo kluczowe było dostępne, gdy ktoś potrzebował punktu do dowolnego typu, a więc void * jako idiom w C. W rzeczywistości działa całkiem dobrze, jeśli interpretujesz void jako pustą strukturę. Wskaźnik void * to adres miejsca, w którym została umieszczona ta pusta struktura.

Rzuty z pustki * na T * dla innych typów T również sprawdzają się z tą perspektywą. Rzuty wskaźników są kompletnym oszustwem, które działają na większości popularnych architektur, aby wykorzystać fakt, że jeśli związek typu T ma element z podtypem S umieszczony fizycznie na początku T w układzie pamięci, to rzutowanie S * na T * i odwrotnie, użycie tego samego adresu fizycznego maszyny zwykle się sprawdza, ponieważ większość wskaźników maszynowych ma jedną reprezentację. Zastąpienie typu S typem void daje dokładnie ten sam efekt, a więc rzucanie do / z void * działa.

Język programowania PARLANSE dość ściśle realizuje powyższe pomysły. Zrobiliśmy błąd w jego projekcie i nie zwróciliśmy szczególnej uwagi na „void” jako typ zwracany i dlatego mamy langauge słowa kluczowe dla procedury. Jest to głównie prosta zmiana składni, ale jest to jedna z rzeczy, do których nie możesz się dostać, gdy otrzymasz duży kod działający w języku.


2

W języku c # użyjesz słowa kluczowego void, aby wskazać, że metoda nie zwraca wartości:

public void DoSomeWork()
{
//some work
}

4
Większość ludzi nie zdaje sobie sprawy, że void mapuje do struktury System.Void
RichardOD

2

Trzy przypadki użycia dla void:

  1. Sygnatury funkcji. void foo(int bar)nie zwraca wartości. int bar(void)nie podejmuje żadnych parametrów, ale jest to zwykle wyrażone listy pusty argument: int bar(). Użycie w tym miejscu słowa kluczowego void odpowiada jego znaczeniu w języku angielskim.

  2. Ogólny wskaźnik najwyższego typu, void *który wskazuje na nieokreślone dane i nie można go wyłuskać. Tutaj znaczenie pustki różni się od innych znaczeń pustki: typ uniwersalny vs. brak typu.

  3. W rzutach, (void) new Foo(this)które oznaczają, że wartość zwracana jest celowo odrzucana. Tutaj użycie słowa kluczowego również odpowiada jego znaczeniu w języku angielskim.

Przypadki 1 i 2 zostały już omówione przez @Gerald, ale sprawa 3 nie została jeszcze rozwiązana.


2

Jeśli wyjaśniasz koncepcję początkującemu, pomocne może być użycie analogii. Użycie słowa „void” we wszystkich tych przypadkach jest analogiczne w znaczeniu do strony w książce, na której znajdują się słowa „Ta strona została celowo pozostawiona pusta”. Ma to na celu rozróżnienie kompilatora między czymś, co powinno być oznaczone jako błąd, a typem, który celowo ma pozostać pusty, ponieważ jest to zachowanie, którego chcesz.

Zawsze pojawia się w kodzie tam, gdzie normalnie można się spodziewać pojawienia się typu, takiego jak typ zwracany lub typ wskaźnika. Dlatego w C # void mapuje do rzeczywistego typu CLR, System.Void, ponieważ jest typem samym w sobie.

Niektóre języki programowania nigdy nie rozwinęły pojęcia pustki, podobnie jak niektóre kultury ludzkie nigdy nie wymyśliły pojęcia liczby zero. Void reprezentuje ten sam postęp w języku programowania, jaki pojęcie zera reprezentuje dla ludzkiego języka.


Uwaga dotycząca twojego ostatniego zdania - pamiętaj, że dotyczy to tylko języków z typami statycznymi. Języki z typami dynamicznymi nie potrzebują void, ponieważ ich metody mogą po prostu niczego nie zwracać - „void” jest implikowany przez brak zwracania czegokolwiek innego.
Mark Embling

Korekta mojego ostatniego komentarza - chciałem powiedzieć ostatni akapit (nie zdanie).
Mark Embling

1

To znaczy „brak wartości”. Używasz void, aby wskazać, że funkcja nie zwraca wartości lub że nie ma parametrów lub obu. Jest to bardzo zgodne z typowymi zastosowaniami słowa void w języku angielskim.

Nie należy mylić wartości Void z wartością null. Null oznacza dla zmiennej, której adres znajduje się na stosie, wartość na stercie dla tego adresu jest pusta.


0

Void jest używany tylko w sygnaturach metod. W przypadku typów zwracanych oznacza to, że metoda nie zwróci niczego do kodu wywołującego. W przypadku parametrów oznacza to, że żadne parametry nie są przekazywane do metody

na przykład

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

W C # możemy pominąć void dla parametrów i zapisać powyższy kod jako:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

Nie należy mylić wartości Void z wartością null. Null oznacza dla zmiennej, której adres znajduje się na stosie, wartość na stercie dla tego adresu jest pusta.


0

Void to niekompletny typ, który z definicji nie może być lwartością. Oznacza to, że nie można mu przypisać wartości.

Więc też nie może mieć żadnej wartości.



-1

Void oznacza, że ​​wartość zwracana przez funkcję nie jest wymagana we wszystkich trzech językach.


-1

Void jest odpowiednikiem Sub.


Tylko jako typ zwracany. Przychodzą mi do głowy jeszcze trzy zastosowania void: void arguments (funkcja nic nie pobiera), void pointers (bez określonego typu wskaźnika) i void casts (discard value).
c4757p
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.