为什么GCC说变量未被使用?

时间:2017-10-23 05:11:15

标签: c gcc

当我设置-Wall标志时,GCC说 snr_db 未使用,但使用了此变量。当我在for的范围之外初始化它时,gcc会停止警告我。有谁知道为什么会这样?

double snr_db;
double snr_db_step = #WHATHEVER

for (int interval = 1, snr_db = 20.0; interval <= intervals; interval++, snr_db -= snr_db_step) {
    snr_lin = pow(10.0, snr_db / 10.0);
    bit_err_rate = ber_bpsk(snr_lin);
    //CODE CONTINUES
}

4 个答案:

答案 0 :(得分:12)

实际上没有使用它。你宣布它为double -

double snr_db; // this is unused 

但是在for循环 -

for (int interval = 1, snr_db = 20.0; ..)

snr_db int在这里{与int x,y;相同,两者都是int,是声明的一部分)在阴影上,在这个循环体上面声明了一个。

因此,double snr_db;仍未使用。

你可以这样做 -

double snr_db;
int interval; 

for(interval = 1, snr_db =20.0;..){....}  // only intialization
 /* ^^^^^^^^^^^^^^^^^^^^^^^^ this would be a different case from above as here
',' does work as comma operator therefore, evaluating both the expressions. */

答案 1 :(得分:5)

您的for循环声明了两个 int个变量,其中包括一个(同样容易引起混淆的snr_db)变量,它们会遮蔽外部double一个嵌套的词汇scope。所以海湾合作委员会是对的。

(根据经验,相信GCC编译器提供的警告经过极度测试和同行评审,因此信任编译器比您自己的代码更多)功能

您应该在 snr_db = 20.0;循环之前指定for ,在您的情况下,这是唯一理智的事情。

您可以使用comma operator,但这会使您的代码无法读取:

for (int interval = (snr_db = 20.0), 1;  ///unreadable so confusing

因此我不建议这样做。

答案 2 :(得分:4)

现有答案已经解决了问题的根源:此for循环

for (int interval = 1, snr_db = 20.0; [...]; [...]) {

声明两个int类型的变量,其中一个碰巧隐藏了外部作用域的double snr_db。为了更深入的理解,让我们添加一些背景知识。

来自 N1570 (latest draft for C11),§6.8.5.3p1

  

声明

     

for ( clause-1 ; expression-2 ; expression-3 < / em> ) 声明

     

表现如下:表达式 expression-2 是控制表达式   在每次执行循环体之前进行评估。表达式表达式-3 是   在每次执行循环体后评估为void表达式。如果 clause-1 是a   声明,它声明的任何标识符的范围是声明的剩余部分   整个循环,包括其他两个表达式;它是按执行顺序到达的   在第一次评估控制表达之前。如果 clause-1 是一个表达式,那就是   在第一次评估控制表达之前评估为空表达。

因此,对于for子句-1 可以是声明表达式。在您的示例中,它是声明。在声明中,逗号具有分隔多个声明符的含义,声明多个相同类型的对象。

另一方面,在表达式中,逗号是一个运算符,它计算两个操作数 sequenced ,并且评估结果是右侧操作数的结果。这通常也用在for循环中。由于子句-1 被评估为空表达式,结果无关紧要,只有副作用是相关的。因此,正确编写代码的一种方法如下:

[...]
int interval;
for (interval = 1, snr_db = 20.0; [...]; [...]) {

现在, clause-1 是一个表达式,逗号运算符分隔两个不同的赋值表达式(具有为变量设置新值的副作用)。但是这种形式的缺点是interval的范围不必要地扩展到你的循环范围。

当然,声明可以在其初始值设定项中包含 表达式,因此有一种方法可以将完全写入你的内容原本想要的看起来像这样:

for (int interval = (snr_db = 20.0), 1; [...]; [...]) {

现在,只声明interval并且其初始值设定项使用逗号运算符首先执行snr_db = 20.0的副作用,但仍然评估为1(右侧)逗号的一边)来初始化interval。虽然这是正确的,但作为高级C程序员,您应该了解它是如何工作的,从不在实践中编写此类代码。要求即使是经验丰富的程序员停下来思考阅读代码时究竟是做什么,这太令人困惑了。

因此,最好的选择是将interval的声明保留为子句-1 ,并在循环之前将作业移至snr_db

snr_db = 20.0;
for (int interval = 1; [...]; [...]) {

答案 3 :(得分:0)

因为for循环中的snr_db是临时变量,而不是外部作用域变量。