在C,C ++和C#中,void是什么意思?

寻找VOID这个词来自何处的基本原理,以及为什么它会被称为无效。 这个问题的意图是帮助那些没有C经验的人,突然看到一个基于C的代码库。

基本上这意味着“没有”或“没有types”

有3个基本的方法,使用void:

  1. 函数参数: int myFunc(void) – 函数不需要任何东西。

  2. 函数返回值: void myFunc(int) – 该函数不返回任何内容

  3. 通用数据指针: void* data – 'data'是指向未知types数据的指针,不能被解除引用

注意:函数参数中的void在C ++中是可选的,所以int myFunc()int myFunc(void)是完全一样的,在C#中完全省略了。 它总是需要一个返回值。

我一直认为这是不存在的 。 下面是C语言中与使用缺席相匹配的四种情况

  • R f(void) – function参数不存在
  • void f(P) – 返回值不存在
  • void *p – 指向的types不存在
  • (void) p – 值的使用不存在

其他C后裔用于其他事情。 D编程语言在初始化程序不存在的情况下使用它

  • T t = void; – 初始化值不存在

这意味着“没有价值”。 你可以使用void来表示一个函数不返回一个值,或者它没有参数或者两者都有。 与英文单词void的典型用法非常一致。

有两种方法可以使用void:

 void foo(void); 

要么

 void *bar(void*); 

第一个表示没有参数被传递,或者没有参数被返回。

第二个告诉编译器没有与数据有效关联的types,这意味着在转换为已知types之前,不能使用指向的数据。

例如,当你有一个调用函数的参数不能被提前知道的接口的时候,你会看到void*被使用了很多。

例如,在Linux Kernel推迟工作的时候,你将设置一个函数在后面的时间运行,给它一个指向要运行的函数的指针和一个指向要传递给函数的数据的指针:

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

然后一个内核线程遍历延迟工作的列表,当它到达这个节点时,它有效地执行:

 bar(somedata); 

然后在酒吧你有:

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

它表示函数中没有返回值。

一些语言有两种子程序:程序和function。 过程只是一系列操作,而函数是返回结果的一系列操作。

在C及其衍生物中,两者的区别并不明确。 一切都基本上是一个function。 void关键字指示它不是“实际”函数,因为它不返回值。

把虚空看成是“空洞的结构”。 让我解释。

每个函数都有一个参数序列,每个参数都有一个types。 实际上,我们可以将参数打包成一个结构,结构槽对应于参数。 这使得每个函数都有一个参数。 同样,函数产生一个结果,它有一个types。 它可能是一个布尔值,也可能是浮点数,也可能是一个结构,包含任意其他types的值。 如果我们想要一个具有多个返回值的语言,只要坚持把它们打包成一个结构就很容易。 实际上,我们总是可以坚持一个函数返回一个结构。 现在每个函数只需要一个参数,并且只产生一个值。

现在,当我需要一个产生“no”值的函数时会发生什么? 那么,考虑一下当我用3个时隙形成一个结构时我得到了什么:它拥有3个值。 当我有两个插槽,它拥有两个值。 当它有一个插槽,一个值。 当它有零插槽,它保存…呃,零值,或“没有”价值“所以,我可以想到一个函数返回void作为返回一个不包含值的结构,甚至可以决定”无效“只是空的结构所代表的types的同义词,而不是语言中的关键字(也许它只是一个预定义的types:)

同样,我可以将一个不需要值的函数想象为接受一个空的结构,例如“void”。

我甚至可以用这种方式来实现我的编程语言。 传递一个void值占用零字节,所以传递void值只是传递任意大小的其他值的特殊情况。 这使编译器很容易处理“无效”结果或参数。 你可能想要一个可以抛出函数结果的语言特性; 在C中,如果在以下语句中调用非void结果函数foo:foo(…); 编译器知道foo会产生一个结果,而忽略它。 如果void是一个值,这是完美的,现在的“程序”(这只是一个函数的形容词,无效的结果)只是普通函数的特殊情况。

虚空*有点有趣。 我不认为Cdevise师以上述方式认为是无效的; 他们只是创build了一个关键字 当有人需要一个任意types的点时,该关键字是可用的,因此void *作为C中的习惯用法。如果将void作为空的结构解释,它实际上工作得非常好。 void *指针是放置了空结构的地址的地址。

对于其他typesT,从void *转换到T *也可以用这个angular度来解决。 指针转换是一个完全的作弊工具,在大多数常见的体系结构中,利用了如下事实:如果一个复合typesT在其存储布局的物理开始T处具有一个带有子typesS的元素,则将S *转换为T *反之亦然,使用相同的物理机器地址往往是成功的,因为大多数机器指针有一个单一的表示。 用typesvoidreplacetypesS给出了完全相同的效果,因此可以将结果输出到void *。

PARLANSE编程语言非常接近地实现了上述想法。 我们对其devise进行了伪装,并没有把“空白”作为一种回归的方式予以关注,因此有程序上的关键词。 它大多只是一个简单的语法变化,但是一旦你在一种语言中得到一个庞大的身体工作代码,你就没有办法解决这个问题。

在C#中,您将使用void关键字来指示方法不会返回值:

 public void DoSomeWork() { //some work } 

void的三个用例:

  1. function签名。 void foo(int bar)不返回值。 int bar(void)不带任何参数,但通常用空参数列表来表示: int bar() 。 void关键字的使用在这里对应于它的英文含义。

  2. generics顶级指针void *指向未指定的数据,不能被解除引用。 这里void的含义与void的其他含义不同:universal type vs. no type。

  3. (void) new Foo(this)这样的expression式中,表示返回值被故意抛弃。 这里的关键字用法也与它的英文意思相匹配。

案例1和案例2已经被@Gerald覆盖,但是案例3还没有得到解决。

如果你正在向初学者解释这个概念,那么使用类比可能会有帮助。 在所有这些情况下使用无效的含义类似于书中的页面,该页面具有以下词语:“该页面故意留空”。 这是区分到应该被标记为错误的东西之间的编译器,而不是故意留空的types,因为这是你想要的行为。

它总是出现在你希望看到types出现的代码中,例如返回types或指针types。 这就是为什么在C#中,void映射到实际的CLRtypesSystem.Void,因为它本身就是一个types。

有些编程语言从来没有开发出void的概念,就像一些人类文化从未发明过零号的概念一样。 虚拟表示在编程语言中的相同的进步,因为零的概念代表人类语言。

这意味着“没有价值”。 你可以使用void来表示一个函数不返回一个值,或者它没有参数或者两者都有。这与void的单词在英语中的使用非常一致。

虚空不应与null混淆。 Null表示地址在堆栈上的variables,堆的值是空的。

Void仅用于方法签名。 对于返回types,这意味着方法不会返回任何东西到调用代码。 对于参数来说,它没有parameter passing给方法

例如

 void MethodThatReturnsAndTakesVoid(void) { // Method body } 

在C#中,我们可以省略参数的void,并可以将上面的代码写成:

 void MethodThatReturnsAndTakesVoid() { // Method body } 

虚空不应与null混淆。 Null表示地址在堆栈上的variables,堆的值是空的。

空格是一个不完整的types,通过定义不能是一个左值。 什么意思,它不能得到一个价值。

所以它也不能保持任何价值。

无效意味着你不会从函数或方法返回任何值

Void表示从三种语言的函数返回types都不需要任何值。

Void相当于Visual Basic的Sub。