web-dev-qa-db-fra.com

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

Vous cherchez à obtenir les bases sur lesquelles le terme "void" vient, et pourquoi il est appelé void. L’intention de la question est d’aider une personne qui n’a pas d’expérience C et qui cherche soudainement une base de code basée sur C.

163
Nick Katsivelos

Fondamentalement, cela signifie "rien" ou "pas de type"

Il y a 3 façons basiques d’utiliser void:

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

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

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

Remarque: la variable void d'un argument de fonction est facultative en C++. Par conséquent, int myFunc() est exactement identique à int myFunc(void) et est complètement omis en C #. Il est toujours requis pour une valeur de retour.

217
Gerald

Je l'ai toujours pris pour signifier absent. Voici quatre cas en langage C qui correspondent à cette utilisation de absent

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

D'autres descendants du C l'utilisent pour autre chose. Le langage de programmation D l'utilise dans les cas où un initialiseur est absent

  • T t = void; - la valeur d'initialisation est absent
31

Il y a deux façons d'utiliser void:

void foo(void);

ou

void *bar(void*);

Le premier indique qu'aucun argument n'est transmis 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 tant qu'elles ne sont pas converties en un type connu.

Par exemple, vous verrez que void* est très 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 de travail, vous allez configurer une fonction à exécuter à un moment ultérieur en lui attribuant un pointeur sur la fonction à exécuter et un pointeur sur les données à transmettre à 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, lorsqu'il arrive à ce nœud, il s'exécute efficacement:

bar(somedata);

Alors au bar vous avez:

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

Cela signifie "pas de valeur". Vous utilisez void pour indiquer qu'une fonction ne renvoie pas de valeur ou qu'elle ne contient aucun paramètre, ni les deux. Quasiment conforme aux utilisations typiques de Word void en anglais.

13
sharptooth

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

Certaines langues ont deux sortes de sous-routines: les procédures et les 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 renvoie un résultat.

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

4
Rik

Pensez à vide en tant que "structure vide". Laissez-moi expliquer.

Chaque fonction prend une séquence de paramètres, chaque paramètre ayant un type. En fait, nous pourrions regrouper les paramètres dans une structure, avec les slots 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, ou d'une valeur flottante, ou d'une structure contenant un ensemble arbitraire d'autres valeurs typées. Si nous voulons une langue ayant plusieurs valeurs de retour, il est facile d'insister pour qu'elles soient intégrées dans une structure. En fait, nous pourrions toujours insister pour qu'une fonction retourne une structure. Désormais, chaque fonction prend exactement un argument et produit exactement une valeur.

Maintenant, que se passe-t-il quand j'ai besoin d'une fonction qui produit "pas" de valeur? Bien, considérons ce que je reçois quand je forme une structure avec 3 slots: elle contient 3 valeurs. Quand j'ai 2 emplacements, il détient deux valeurs. Quand il a un emplacement, une valeur. Et quand il a zéro slot, il tient ... euh, zéro, ou "no" valeur. Donc, je peux penser à une fonction retournant void comme renvoyant une structure ne contenant aucune valeur. Vous pouvez même décider que "void" est juste un synonyme pour le type représenté par la structure vide, plutôt qu'un mot clé dans le langage (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. Passer une valeur de vide prend zéro octet. Par conséquent, transmettre des valeurs de vide est simplement un cas spécial 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 puisse jeter un résultat de fonction; en C, si vous appelez la fonction de résultat non-vide 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 les "procédures" (qui sont simplement un adjectif pour une fonction avec un résultat void) ne sont plus que des cas particuliers triviaux de fonctions générales.

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

Les conversions de vide * à T * pour les autres types T fonctionnent également avec cette perspective. Les lancers de pointeurs sont une astuce complète qui fonctionne sur les architectures les plus courantes pour tirer parti du fait que si un type composé T a un élément de sous-type S placé physiquement au début de T dans son agencement de stockage, puis transforme S * en T * et inversement, utiliser la même adresse physique de la machine a tendance à marcher, car la plupart des pointeurs de la machine ont une représentation unique. Remplacer le type S par le type void donne exactement le même effet, et le casting vers/depuis void * fonctionne donc.

Le langage de programmation PARLANSE implémente assez étroitement les idées ci-dessus. Nous avons fait une gaffe dans sa conception, et nous n’avons pas fait très attention à "vide" comme type de retour et avons donc des mots-clés en langue pour la procédure. Il s’agit pour la plupart d’un simple changement de syntaxe, mais c’est l’une des choses à laquelle vous n’arrivez pas une fois que vous avez obtenu un code de gros corps dans un langage.

3
Ira Baxter

En c #, vous utiliseriez le mot clé void pour indiquer qu'une méthode ne renvoie pas de valeur:

public void DoSomeWork()
{
//some work
}
2
Charlie

Si vous expliquez le concept à un débutant, il peut être utile d’utiliser une analogie. L'utilisation de vide dans tous ces cas a une signification analogue à celle d'une page d'un livre contenant les mots suivants: "Cette page est laissée intentionnellement blanche". Il s'agit de différencier le compilateur de ce qui doit être signalé comme une erreur par rapport à un type qui doit être laissé intentionnellement vide car il s'agit du comportement souhaité.

Il apparaît toujours dans le code où normalement vous devriez 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 réel de CLR, 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 la même avancée dans un langage de programmation que le concept de zéro en langage humain.

2
TimF

Trois cas d'utilisation pour null:

  1. Signatures de fonction. void foo(int bar) ne renvoie pas de valeur. int bar(void) ne prend aucun paramètre mais ceci est généralement exprimé avec une liste d'arguments vide: 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 de vide est différente des autres significations de vide: type universel vs aucun type.

  3. Dans les transtypes tels que (void) new Foo(this) pour indiquer que la valeur de retour est délibérément supprimé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é.

2
laalto

Cela signifie "pas de valeur". Vous utilisez void pour indiquer qu'une fonction ne renvoie pas de valeur ou qu'elle ne contient aucun paramètre, ni les deux. Cela correspond beaucoup aux utilisations habituelles de Word void en anglais.

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

1
AVI

Le vide est un type incomplet qui, par définition, ne peut pas être une valeur. Cela signifie qu'il ne peut pas se voir attribuer une valeur.

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

0
dhein

Nul est utilisé uniquement dans les signatures de méthode. Pour les types de retour, cela signifie que la méthode ne renverra rien au code appelant. Pour les paramètres, cela signifie qu'aucun paramètre n'est transmis à 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 suit:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

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

0
Rashmi Pandit