编程语言应用

首页 » 常识 » 常识 » 奇怪的C语言代码,在变量前加上void
TUhjnbcbe - 2023/4/22 19:59:00
患了白癜风如何治疗 http://m.39.net/pf/a_4673902.html

C语言的语法极其简洁,即使是初次接触编程语言的初学者也能很快学完它的语法。不过,C语言也是一门“灵活得过了头”的编程语言,对于很多初学者来说,编写C语言程序就好像拿着一堆最基本的砖块,要修建一座大厦一样,茫然找不到方向。

茫然找不到方向

奇怪的C语言代码

对于初学者来说,阅读项目源代码是学习和巩固C语言编程能力的一个好方法——从前辈们的一些优秀C语言项目中,我们能够学到很多编写程序方面的思考方式,也就是一些程序员所谓的“编程思维”,看得多了,编写C语言程序自然就手到擒来了。

不过虽然C语言的语法简单,但是我们总会看到一些令人迷惑的代码,例如下面这个函数,它来自某个开源项目,为了讨论主题,我将一些不相关的细节略去了:

void*fun(void*ud,void*ptr,intsize){

(void)ud;

(void)size;

//其他代码,未用到ud和size参数

...

}

fun()函数中省略掉的代码没有使用到ud和size参数,这里有两个问题:一是既然用不到这两个参数,为什么不删去它们呢?再就是两个参数前的(void)类型转换有什么用呢?

为什么不删除多余参数呢?

首先考虑第一个问题

前文提到fun()函数来自一个C语言程序开源项目,该项目比较复杂,但是我们知道再复杂的程序项目也是一行一行代码敲出来的,而且,在后续的开发中,可能会修改之前的设计。明白这一点,要回答第一个问题就简单了。

可能在之前的设计中,fun()函数是用到了ud和size参数的,只是后来的设计发现fun()函数不必使用这两个参数,但是发现整个C语言项目由大量使用fun()函数的代码。

如果删去这两个参数,那么fun()函数的原型就改变了,开发人员将不得不逐个修改整个C语言项目中所有调用fun()函数的代码,这样的工作量巨大,极其容易给C语言项目引入bug。因此,倒不如继续保留fun()函数的原型不变了。

另外,读者应该已经知道C语言是不支持重载的,因为如果该C语言项目需要使用fun()函数对接某些API,那么fun()函数就必须符合API指定的原型,因此fun()函数中有未使用的参数其实是“身不由己”的。

“身不由己”

还有一种情况,fun()函数可能是某个“函数家族”里的一个,该“函数家族”由一个统一的函数指针管理(为了方便,以及提高效率,实例可参考我之前文章。),因为“统一的函数指针”类型是固定的,所以fun()函数的原型必须符合该函数指针的原型,所以,即使fun()函数用不到ud和size参数,也是不能将其删除的,否则就无法通过“统一的函数指针”调用fun()函数了。

当然了,也有可能纯粹是因为开发人员懒得修改fun()函数原型。现在明白了第一个问题,再来考虑第二个问题。

为什么要在未使用的参数前添加(void)呢?

在解答这个问题之前,我们先做一个实验:编写下面这段C语言代码,也即删去(void)ud和(void)size:

void*fun(void*ud,void*ptr,intsize){

//其他代码,未用到ud和size参数

...

在编译这段C语言代码时,编译器常常会给出下面这样的“参数未使用(unusedparameter)”警告信息:

t.c:Infunction‘fun’:t.c:3:22:warning:unusedparameter‘ud’[-Wunused-parameter]

忽略编译器发出的警告信息,是非常不好

很多C语言程序员会忽略编译器发出的警告信息,但这是非常不好的习惯,解决警告信息能够帮助我们最大程度地避免最终C语言程序出现bug。要解决“参数未使用(unusedparameter)”警告信息,最直接的方法就是使用它了:

void*fun(void*ud,void*ptr,intsize){

ud;

//其他代码,未用到ud和size参数

...

}

但是编译器又会给出“C语言语句无效”的警告信息:

t.c:5:5:warning:statementwithnoeffect[-Wunused-value]

ud;^~

为了避免出现这样的警告信息,我们当然可以对size和ud参数做一些其他操作,例如:

void*fun(void*ud,void*ptr,intsize){

ud=(void*)size;

//其他代码,未用到ud和size参数

...

}

可是这样虽然能够避免C语言编译器发出警告,但是这样会让其他阅读代码的程序员费解:“NND,ud=(void*)size;这句到底什么意思呢?”

因此,避免编译器发出参数未使用的警告信息,最好不要像上面这样操作,采用(void)操作更好:

void*fun(void*ud,void*ptr,intsize){

(void)ud;(void)size;

//其他代码,未用到ud和size参数

...

}

C语言程序员都知道void表示空,因此(void)ud和(void)size显然表示不关心ud和size的操作。这样一来,我们的意图一眼就能看出,而且还能避免编译器发出警告信息。

小结

在C语言程序开发中,定义函数时,有时会不可避免的定义一些使用不到的参数,这时编译程序时,编译器往往会发出警告信息。C语言程序员不应该忽视每一个警告信息,因此可以借助(void)操作屏蔽掉这样的警告信息,以免更重要的编译器警告被淹没在信息流里。

点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就

1
查看完整版本: 奇怪的C语言代码,在变量前加上void