点击上方蓝字关注我,我们一起学编程
欢迎小伙伴们分享、转载、私信、赞赏

微信搜索:编程笔记本。
微信搜索:编程笔记本。
微信搜索:编程笔记本。

昨天在 review 同事的一个 MR 时,发现了一个比较有趣的问题,记录如下。

同时的 MR 修复的大概是这样一个问题:函数内部定义的某些局部变量仅用于 Log 语句,当 Log 关闭时,这些局部变量在整个函数作用域内就都未被使用过,所以在编译的时候就会报**变量未使用**的警告信息。

程序中的 Log 语句主要是帮助开发人员调试程序的,主要是打印一些程序运行的中间状态和提示信息。所以在一般的生产环境,特别是在内存比较有限的场景下,通常都是关闭 Log 的。

场景还原:

#include <stdio.h>

#define DEBUG_CONTEXT

void fun(void)
{
    int age = 1;
#ifdef DEBUG_CONTEXT
    printf("The age is %d.\n", age);
#endif
}

int main()
{
    fun();
    return 0;
}

Tips: 需要打开编译器的警告选项,才能输出编译器警告。笔者使用的是 gcc 编译器,相应的警告选项为 -Wall

下面我们来编译运行一下:

➜  $ gcc -Wall test.c -o test
➜  $ ./test                  
The age is 1.

微信搜索:编程笔记本。
微信搜索:编程笔记本。
微信搜索:编程笔记本。

如果我们将 Log 语句删除以减小程序体积,我们可以删除用于控制调制的宏:#define DEBUG_CONTEXT 。这样,printf 语句将不会出现在可执行文件中。此时,局部变量 age 就成了未使用的局部变量

#include <stdio.h>

//#define DEBUG_CONTEXT

void fun(void)
{
    int age = 1;
#ifdef DEBUG_CONTEXT
    printf("The age id %d.\n", age);
#endif
}

int main()
{
    fun();
    return 0;
}

再来编译运行一下:

➜  $ gcc -Wall test.c -o test
test.c:7:9: warning: unused variable 'age' [-Wunused-variable]
    int age = 1;
        ^
1 warning generated.

可以看到,由于 printf 不再存在,局部变量 age 就未被使用,所以编译时就会出现 -Wunused-variable 警告。


看到这里,小伙伴是不是以为就结束啦?哈哈哈,下面才是今天的主题哦,且看!

微信搜索:编程笔记本。
微信搜索:编程笔记本。
微信搜索:编程笔记本。

对汇编了解的朋友都知道,函数传入的参数也属于当前函数作用于内的“局部变量”。但我仔细回想了一下,有的时候,我们未使用函数传入的参数好像并没有什么问题啊?

再来测试一下:

#include <stdio.h>

void fun(int num)
{
    printf("Hello,world\n");
}

int main()
{
    fun(0);
    return 0;
}

编译:

➜  $ gcc -Wall test.c -o test
➜  $

可以看到,未使用函数传入的参数并没有报出警告。

最终,在查阅 gcc 文档后,找到根本原因:

In order to get a warning about an unused function parameter, you must either specify -Wextra -Wunused (note that -Wall implies -Wunused), or separately specify -Wunused-parameter.

原来,函数传入的参数有一个其他的名称:function parameter 。从 gcc 文档可以知道,要想报出这样的警告,需要指定 -Wextra 选项。

再来测试一下:

➜  $ gcc -Wextra test.c -o test 
test.c:3:14: warning: unused parameter 'num' [-Wunused-parameter]
void fun(int num)
             ^
1 warning generated.

果然,这时候未使用的函数参数给出了警告信息 -Wunused-parameter

不知道,会不会有小伙伴有这样的疑问:这样的警告信息有什么用呢?
哈哈,看看下面的代码段你就知道啦!

#include <stdio.h>

int add(int n1, int n2, int n3)
{
    return n1 + n2 + n2;
}

int main()
{
    int sum = add(1, 2, 3);
    printf("The sum is %d.\n", sum);

    return 0;
}

有一天,你需要写一个三个数求和的功能,于是你编辑、编译、运行一气呵成,熟练得让人心疼~

➜  $ gcc test.c -o test
➜  $ ./test
The sum is 5.

:报告老师,1 + 2 + 3 = 5 。报告完毕,请指示!
老师:出门左转!!!

其实,我们经常容易手误敲错代码,要命的是有时候并不会触发编译错误,但逻辑已经不对了。就像上面的代码段,我们需要秋 n1n2n3 的和,一不留神把 n3 写成了 n2 。虽然程序不会报错,但是程序已经完全不对了。如果我们打开警告选项,就不会出现这种低级错误了。

➜  $ gcc -Wextra test.c -o test
test.c:3:29: warning: unused parameter 'n3' [-Wunused-parameter]
int add(int n1, int n2, int n3)
                            ^
1 warning generated.

编译器会提示我们,函数参数 n3 未使用。

总结:

  1. -Wall 选项仅仅能检测到未使用的局部变量,要检测未使用的函数参数,需要指定 -Wextra 选项。
  2. 编译器的警告选项最好打开,这能够帮助我们检查到很多问题。

微信搜索:编程笔记本。
微信搜索:编程笔记本。
微信搜索:编程笔记本。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐