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


170

希望了解术语“ 无效 ”的来源以及为什么称为“ 无效 ” 的基础知识。这个问题的目的是为没有C经验的人提供帮助,而他们突然正在寻找基于C的代码库。


2
这个问题混合了3种语言...该旧问题应分为3个不同的问题。
Stargateur '18

Answers:


225

基本上,它的意思是“无”或“无类型”

有3种使用void的基本方法:

  1. 函数参数:int myFunc(void) -函数不执行任何操作。

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

  3. 通用数据指针:void* data -“数据”是指向未知类型数据的指针,无法取消引用

注意:void函数参数in在C ++中是可选的,因此int myFunc()与完全相同int myFunc(void),并且在C#中完全省略了。返回值始终是必需的。


7
虚空中的参数列表是用C ++可选,见stackoverflow.com/questions/416345/...
丹尼尔·埃里克

1
我会使用“没有类型”而不是“没有大小”
Kjetil Joergensen 09年

@Earwicker和kjetijor都是我争论的重点,但是我的不眠之心需要帮助;)谢谢。
杰拉尔德

9
并非不同意,而是在“强制转换为无效”技巧中额外使用了void,以禁止显示未使用值的警告。这有点麻烦,因为它与编译器的解释方式并不完全一致,但是您可以将其解释为“我正在使用此值执行任何操作”。
史蒂夫·杰索普

22
在C ++中,参数列表中的void是可选的。但是,在C语言中,它不是可选的:foo()表示它接受任意数量的任何类型的参数,而foo(void)表示它采用零参数。
亚当·罗森菲尔德2009年

33

我一直认为它是缺席的。以下是C语言中与这种用法相符的四种情况

  • R f(void)- 缺少功能参数
  • void f(P)-返回值是不存在的
  • void *p-所指向的类型不存在
  • (void) p- 缺乏价值使用

其他C后代将其用于其他用途。该D编程语言使用它的情况下的初始化是不存在的

  • T t = void;- 缺少初始化值

4
怎么(void)p办?我没有完全理解“缺乏价值使用”的意思。
Yashas

@Yashas如果有人对此(void) var;声明也感到困惑,我可以在stackoverflow.com/q/21045615找到详细的答案。
Arnie97 '19

14

有两种使用void的方法:

void foo(void);

要么

void *bar(void*);

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

第二个告诉编译器没有与数据有效关联的类型,这意味着在将其转换为已知类型之前,您无法使用指向的数据。

例如,void*当您有一个接口调用一个函数(其参数无法提前知道)时,您会发现使用了很多。

例如,在Linux内核中,当推迟工作时,您将为函数提供指向要运行的函数的指针和指向要传递给该函数的数据的指针,以设置稍后运行的函数:

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 */;
}

13

这意味着“没有价值”。您可以void用来指示函数不返回值或没有参数,或两者都不返回。与英语中空词的典型用法非常一致。


4

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

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

在C及其派生词中,两者之间的区别并不明显。基本上所有东西都是功能。该void关键字表明它不是一个“实际”的功能,因为它没有返回值。


3

将无效视为“空结构”。让我解释。

每个函数都有一个参数序列,其中每个参数都有一个类型。实际上,我们可以将参数打包成一个结构,结构槽对应于这些参数。这使得每个函数只有一个参数。类似地,函数产生一个具有类型的结果。它可以是布尔值,也可以是浮点数,也可以是包含任意一组其他类型值的结构。如果我们想要一个具有多个返回值的语言,可以很容易地坚持将它们打包到一个结构中。实际上,我们总是可以坚持认为函数要返回结构。现在,每个函数只使用一个参数,并产生一个值。

现在,当我需要一个产生“无”值的函数时会发生什么?好吧,考虑一下当我形成一个具有3个插槽的结构时得到的结果:它包含3个值。当我有2个插槽时,它包含两个值。如果有一个插槽,则为一个值。而且当它有零个插槽时,它保存着……呃,零值或“无”值。因此,我可以认为函数返回void就是返回不包含任何值的结构,甚至可以确定“ void”只是空结构表示的类型的同义词,而不是语言中的关键字(也许只是预定义的类型:)

类似地,我可以认为一个不需要任何值的函数就可以接受一个空结构,例如“ void”。

我什至可以用这种方式实现我的编程语言。传递void值占用零字节,因此传递void值只是传递任意大小的其他值的一种特殊情况。这使编译器可以轻松地处理“无效”结果或参数。您可能想要一种可以丢弃函数结果的语言功能。在C中,如果在以下语句中调用非无效结果函数foo:foo(...); 编译器知道foo会产生结果,而只是忽略它。如果void是一个值,则可以很好地工作,现在“过程”(对于具有void结果的函数只是形容词)只是一般函数的平凡特殊情况。

虚空*有点有趣。我不认为C设计师会以上述方式考虑到void。他们只是创建了一个关键字。当有人需要指向任意类型的点时,该关键字可用,因此void *作为C中的惯用法。如果将void解释为空结构,则实际上效果很好。void *指针是放置空结构的地方的地址。

对于其他类型T,从void *到T *的转换也可以从这种角度得出。指针强制转换是在大多数常见体系结构上都能发挥作用的完整作弊,以利用以下事实:如果复合类型T的存储布局中的T开头物理上放置了一个子类型为S的元素,则将S *转换为T *并反之亦然,因为大多数机器指针只有一个表示形式,所以倾向于使用相同的物理机器地址。用void类型替换类型S可获得完全相同的效果,因此可以对void *进行强制转换。

PARLANSE编程语言非常紧密地实现了上述想法。我们对它的设计感到厌烦,并且没有密切注意“ void”作为返回类型,因此有用于过程的langauge关键字。它主要是一个简单的语法更改,但是一旦获得了一种语言的大量主体工作代码,您就不会了解它。



2

三种无效的用法案例:

  1. 功能签名。void foo(int bar)不返回值。int bar(void)不带任何参数,但是通常用空参数列表表示int bar()。这里使用void关键字与其在英语中的含义相对应。

  2. 指向void *未指定数据且无法取消引用的通用顶级指针。在这里,void的含义与void的其他含义不同:通用类型与无类型。

  3. 在强制转换中,例如(void) new Foo(this)表示返回值被故意丢弃。此处,关键字用法也与英语中的含义匹配。

@Gerald已涵盖案例1和2,但案例3尚未解决。


2

如果您要向初学者解释该概念,那么使用类比可能会有所帮助。在所有这些情况下,void的使用类似于一本书中的页面,该页面上带有以下单词:“此页面故意留为空白”。它是为了区别于编译器,在应该标记为错误的内容与故意留空的类型之间进行区分,因为这是您想要的行为。

它总是出现在通常希望看到一种类型的代码中,例如返回类型或指针类型。这就是为什么在C#中void将映射到实际的CLR类型System.Void的原因,因为它本身就是类型。

某些编程语言从未提出过空的概念,就像某些人类文化从未发明零数字的概念一样。无效代表编程语言的进步,零代表人类语言。


关于您的最后一句话,请注意-请记住,这仅适用于静态类型的语言。动态类型的语言不需要void,因为它们的方法可能只是不返回任何内容-缺少任何其他内容都暗示了“ void”。
Mark Embling,2009年

更正我的最后一条评论-我的意思是说最后一段(不是句子)。
Mark Embling,2009年

1

这意味着“没有价值”。使用void表示函数不返回值或不具有参数或两者都不存在,这与英语中单词void的典型用法非常一致。

虚空不应与null混淆。Null表示对于地址在堆栈中的变量,该地址在堆上的值为空。


0

无效仅在方法签名中使用。对于返回类型,这意味着方法将不会向调用代码返回任何内容。对于参数,这意味着没有参数传递给方法

例如

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

在C#中,我们可以省略参数的空白,并可以将上述代码编写为:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

虚空不应与null混淆。Null表示对于地址在堆栈中的变量,该地址在堆上的值为空。


0

Void是不完整的类型,根据定义,它不能是左值。这意味着无法为其分配值。

因此它也不能保留任何值。




-1

无效等效于Visual Basic的Sub。


仅作为返回类型。我可以想到void的另外三种用途:void参数(函数什么也不做),void指针(未指定指针类型)和void强制类型转换(舍弃值)。
c4757p 2009年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.