4

C语言程序开发中的(void)size;有什么用?变量前使用(void)强制转换是什么意思?

 3 years ago
source link: https://blog.popkx.com/c%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84voidsize%E6%9C%89%E4%BB%80%E4%B9%88%E7%94%A8-%E5%8F%98%E9%87%8F%E5%89%8D%E4%BD%BF%E7%94%A8-void/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C语言程序开发中的(void)size;有什么用?变量前使用(void)强制转换是什么意思?

发表于 2019-09-19 20:09:03   |   已被 访问: 644 次   |   分类于:   C语言   |   1 条评论

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

奇怪的C语言代码

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

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

void *fun(void *ud, void *ptr, int size){
    (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, int size){
    // 其他代码,未用到 ud 和 size 参数
    ...
}

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

t.c: In function ‘fun’:
t.c:3:22: warning: unused parameter ‘ud’ [-Wunused-parameter]

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

void *fun(void *ud, void *ptr, int size){
    ud;
    // 其他代码,未用到 ud 和 size 参数
    ...
}

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

t.c:5:5: warning: statement with no effect [-Wunused-value]
     ud;
     ^~

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

void *fun(void *ud, void *ptr, int size){
    ud = (void *)size;
    // 其他代码,未用到 ud 和 size 参数
    ...
}

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

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

void *fun(void *ud, void *ptr, int size){
    (void) ud;
    (void) size;
    // 其他代码,未用到 ud 和 size 参数
    ...
}

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

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

阅读更多:   C语言


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK