Que signifie void en C, C ++ et C #?

170

Vous cherchez à obtenir les principes fondamentaux sur l'origine du terme « vide » et pourquoi il est appelé vide. L'intention de la question est d'aider quelqu'un qui n'a pas d'expérience en C et qui regarde soudainement une base de code basée sur C.

Nick Katsivelos
la source
2
Cette question mélange 3 langues ... cette question héritée doit être divisée en 3 questions différentes.
Stargateur

Réponses:

225

Fondamentalement, cela signifie "rien" ou "aucun type"

Il existe 3 façons de base d'utiliser void:

  1. Argument de fonction: int myFunc(void) - la fonction ne prend rien.

  2. Valeur de retour de void myFunc(int) la fonction : - la fonction ne renvoie rien

  3. Pointeur de données générique: void* data - 'data' est un pointeur vers des données de type inconnu, et ne peut pas être déréférencé

Remarque: l' voidargument dans une fonction est facultatif en C ++, il int myFunc()est donc exactement le même que int myFunc(void), et il est complètement laissé de côté en C #. Il est toujours requis pour une valeur de retour.

Gérald
la source
7
void dans la liste d'arguments est facultatif en C ++, voir stackoverflow.com/questions/416345/…
Daniel Earwicker
1
J'utiliserais "aucun type" plutôt que "aucune taille"
Kjetil Joergensen
@Earwicker et kjetijor, deux bons points dont j'ai débattu, mais mon esprit insomnie avait besoin d'aide;) Merci.
Gerald
9
Pas en désaccord, mais une utilisation supplémentaire de void est dans l'astuce "cast to void" pour supprimer les avertissements pour les valeurs inutilisées. C'est un peu exagéré car cela ne correspond pas vraiment à la façon dont le compilateur interprète les choses, mais vous pouvez interpréter cela comme signifiant "J'utilise cette valeur pour ne rien faire".
Steve Jessop
22
En C ++, void dans la liste d'arguments est facultatif. Cependant, en C, ce n'est PAS optionnel: foo () signifie qu'il prend n'importe quel nombre de paramètres de n'importe quel type, alors que foo (void) signifie qu'il prend zéro paramètre.
Adam Rosenfield
33

J'ai toujours pris cela pour signifier absent . Voici quatre cas en langage C qui correspondent à cette utilisation d' absence

  • R f(void)- Les paramètres de fonction sont absents
  • void f(P)- La valeur de retour est absente
  • void *p- Le type de ce qui est pointé est absent
  • (void) p- L'utilisation de la valeur est absente

D'autres descendants C l'utilisent pour d'autres choses. Le Dlangage de programmation l'utilise pour les cas où un initialiseur est absent

  • T t = void;- la valeur d'initialisation est absente
Johannes Schaub - litb
la source
4
Que fait (void)p-on? Je n'ai pas tout à fait compris ce que vous entendez par «l'utilisation de la valeur est absente».
Yashas
@Yashas Si quelqu'un est également confus au sujet de la (void) var;déclaration, j'ai trouvé des réponses détaillées sur stackoverflow.com/q/21045615 .
Arnie97
14

Il existe deux façons d'utiliser void:

void foo(void);

ou

void *bar(void*);

Le premier indique qu'aucun argument n'est passé ou qu'aucun argument n'est renvoyé.

La seconde indique au compilateur qu'aucun type n'est associé aux données, ce qui signifie que vous ne pouvez pas utiliser les données pointées jusqu'à ce qu'elles soient converties en un type connu.

Par exemple, vous verrez void*beaucoup utilisé lorsque vous avez une interface qui appelle une fonction dont les paramètres ne peuvent pas être connus à l'avance.

Par exemple, dans le noyau Linux, lors du report du travail, vous configurerez une fonction à exécuter ultérieurement en lui donnant un pointeur vers la fonction à exécuter et un pointeur vers les données à passer à la fonction:

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

Ensuite, un thread du noyau passe en revue une liste de travaux différés et quand il arrive sur ce nœud, il s'exécute efficacement:

bar(somedata);

Puis au bar vous avez:

void bar(void* mydata) {
    int *data = mydata;
    /* do something with data */;
}
Robert S. Barnes
la source
13

Cela signifie "aucune valeur". Vous utilisez voidpour indiquer qu'une fonction ne renvoie pas de valeur ou qu'elle n'a aucun paramètre ou les deux. À peu près conforme aux utilisations typiques du mot vide en anglais.

dents acérées
la source
4

Il indique l'absence de valeur de retour dans une fonction.

Certains langages ont deux sortes de sous-programmes: des procédures et des fonctions. Les procédures ne sont qu'une séquence d'opérations, alors qu'une fonction est une séquence d'opérations qui renvoient un résultat.

Dans C et ses dérivés, la différence entre les deux n'est pas explicite. Tout est fondamentalement une fonction. le voidmot-clé indique qu'il ne s'agit pas d'une fonction "réelle", car il ne renvoie pas de valeur.

Rik
la source
3

Pensez au vide comme à la «structure vide». Laisse-moi expliquer.

Chaque fonction prend une séquence de paramètres, où chaque paramètre a un type. En fait, nous pourrions regrouper les paramètres dans une structure, avec les emplacements de structure correspondant aux paramètres. Cela fait que chaque fonction a exactement un argument. De même, les fonctions produisent un résultat, qui a un type. Il peut s'agir d'un booléen, d'un flottant ou d'une structure contenant un ensemble arbitraire d'autres valeurs typées. Si nous voulons un languge qui a plusieurs valeurs de retour, il est facile d'insister simplement pour qu'il soit empaqueté dans une structure. En fait, nous pourrions toujours insister sur le fait qu'une fonction renvoie une structure. Désormais, chaque fonction prend exactement un argument et produit exactement une valeur.

Maintenant, que se passe-t-il lorsque j'ai besoin d'une fonction qui ne produit aucune valeur? Eh bien, considérez ce que j'obtiens lorsque je forme une structure avec 3 emplacements: elle contient 3 valeurs. Quand j'ai 2 emplacements, il contient deux valeurs. Lorsqu'il a un emplacement, une valeur. Et quand il n'a aucun emplacement, il contient ... euh, aucune valeur ou "aucune" valeur ". Donc, je peux penser à une fonction renvoyant void comme renvoyant une structure ne contenant aucune valeur. Vous pouvez même décider que" void " est juste un synonyme du type représenté par la structure vide, plutôt qu'un mot-clé dans la langue (peut-être que c'est juste un type prédéfini :)

De même, je peux penser à une fonction ne nécessitant aucune valeur comme acceptant une structure vide, par exemple, "void".

Je peux même implémenter mon langage de programmation de cette façon. La transmission d'une valeur void prend zéro octet, donc la transmission de valeurs void n'est qu'un cas particulier de transmission d'autres valeurs de taille arbitraire. Cela permet au compilateur de traiter facilement le résultat ou l'argument "void". Vous voulez probablement une fonctionnalité de langage qui peut rejeter un résultat de fonction; en C, si vous appelez la fonction de résultat non-void foo dans l'instruction suivante: foo (...); le compilateur sait que foo produit un résultat et l'ignore simplement. Si void est une valeur, cela fonctionne parfaitement et maintenant les "procédures" (qui ne sont qu'un adjectif pour une fonction avec un résultat void) ne sont que des cas spéciaux triviaux de fonctions générales.

Void * est un peu plus drôle. Je ne pense pas que les designers C aient pensé au vide de la manière ci-dessus; ils viennent de créer un mot-clé. Ce mot-clé était disponible quand quelqu'un avait besoin d'un point sur un type arbitraire, donc void * comme idiome en C. Cela fonctionne plutôt bien si vous interprétez void comme une structure vide. Un pointeur void * est l'adresse d'un endroit où cette structure vide a été placée.

Les moulages de vide * à T * pour les autres types T, fonctionnent également dans cette perspective. Les lancers de pointeurs sont une triche complète qui fonctionnent sur les architectures les plus courantes pour tirer parti du fait que si un type composé T a un élément avec le sous-type S placé physiquement au début de T dans sa disposition de stockage, alors le casting S * en T * et vice versa, l'utilisation de la même adresse de machine physique a tendance à fonctionner, car la plupart des pointeurs de machine ont une seule représentation. Le remplacement du type S par le type void donne exactement le même effet, et donc le lancer vers / depuis void * fonctionne.

Le langage de programmation PARLANSE met en œuvre les idées ci-dessus assez étroitement. Nous avons gaffé dans sa conception, et n'avons pas prêté attention à "void" comme type de retour et avons donc des mots-clés de langue pour la procédure. Il s'agit principalement d'un simple changement de syntaxe, mais c'est l'une des choses auxquelles vous ne vous déplacez pas une fois que vous obtenez un gros code de travail dans un langage.

Ira Baxter
la source
2

Trois cas d'utilisation pour void:

  1. Signatures de fonction. void foo(int bar)ne renvoie pas de valeur. int bar(void)ne prend pas de paramètres , mais cela est généralement exprimée avec la liste vide d'arguments: int bar(). L'utilisation du mot-clé void correspond ici à sa signification en anglais.

  2. Pointeur générique de type supérieur void *qui pointe vers des données non spécifiées et ne peut pas être déréférencé. Ici, la signification du vide est différente des autres significations du vide: type universel contre aucun type.

  3. Dans des casts tels que (void) new Foo(this)pour signifier que la valeur de retour est délibérément jetée. Ici, l'utilisation du mot-clé correspond également à sa signification en anglais.

Les cas 1 et 2 étaient déjà couverts par @Gerald mais le cas 3 n'a pas encore été traité.

laalto
la source
2

Si vous expliquez le concept à un débutant, il peut être utile d'utiliser une analogie. L'utilisation de void dans tous ces cas a un sens analogue à une page d'un livre qui contient les mots suivants: «Cette page est laissée intentionnellement vierge». Il s'agit de faire la différence avec le compilateur entre quelque chose qui devrait être signalé comme une erreur, et un type qui est intentionnellement laissé vide parce que c'est le comportement que vous voulez.

Il apparaît toujours dans le code là où vous vous attendez normalement à voir apparaître un type, tel qu'un type de retour ou un type de pointeur. C'est pourquoi en C #, void correspond à un type CLR réel, System.Void, car il s'agit d'un type en soi.

Certains langages de programmation n'ont jamais développé le concept de vide, tout comme certaines cultures humaines n'ont jamais inventé le concept du nombre zéro. Void représente le même progrès dans un langage de programmation que le concept de zéro représente pour le langage humain.

TimF
la source
Juste une note concernant votre dernière phrase - gardez à l'esprit que cela n'est vrai que pour les langues à typage statique. Les langages dynamiquement typés n'ont pas besoin de void puisque leurs méthodes peuvent simplement ne rien renvoyer - le "vide" est impliqué par l'absence de retour de quoi que ce soit d'autre.
Mark Embling
Correction à mon dernier commentaire - je voulais dire le dernier paragraphe (pas la phrase).
Mark Embling
1

Cela signifie "aucune valeur". Vous utilisez void pour indiquer qu'une fonction ne renvoie pas de valeur ou qu'elle n'a pas de paramètres ou les deux, ce qui correspond beaucoup aux utilisations typiques du mot void en anglais.

Void ne doit pas être confondu avec null. Null signifie que pour la variable dont l'adresse est sur la pile, la valeur sur le tas pour cette adresse est vide.

AVI
la source
0

Void est utilisé uniquement dans les signatures de méthode. Pour les types de retour, cela signifie que la méthode ne retournera rien au code appelant. Pour les paramètres, cela signifie qu'aucun paramètre n'est passé à la méthode

par exemple

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

En C #, nous pouvons omettre le vide pour les paramètres et écrire le code ci-dessus comme:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

Void ne doit pas être confondu avec null. Null signifie que pour la variable dont l'adresse est sur la pile, la valeur sur le tas pour cette adresse est vide.

Utilisateur SO
la source
0

Void est un type incomplet qui, par définition, ne peut pas être une lvalue. Cela signifie qu'il ne peut pas recevoir de valeur.

Donc, cela ne peut pas non plus avoir de valeur.

Dhein
la source
-1

void signifie que vous ne retournerez aucune valeur de la fonction ou de la méthode

Hannoun Yassir
la source
-1

Void signifie qu'aucune valeur n'est requise dans le type de retour d'une fonction dans les trois langues.

Nakul Chaudhary
la source
-1

Void est l'équivalent du Sub de Visual Basic.

cyclo
la source
Uniquement comme type de retour. Je peux penser à trois autres utilisations de void: les arguments vides (la fonction ne prend rien), les pointeurs vides (aucun type de pointeur spécifié) et les casts void (valeur de rejet).
c4757p