GCC 意外警告?

问题描述 投票:0回答:2

我正在做一个个人项目,我做了这种代码(在一个静态的小辅助函数中):

char *tmp = NULL;
if ((tmp = strchr(mode, 'b') != NULL) && tmp - mode < 3) return BINARY_MODE;
else // ...

然后当我尝试使用 GCC 12 (Ubuntu 12.2.0-3ubuntu1) 进行编译时,我收到了这个警告:

warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
   31 |     if ((tmp = strchr(mode, 'b') != NULL) && tmp - mode < 3) return BINARY_MODE;
      |              ^

我尝试解决问题的唯一方法(至少抑制了警告)是在条件之前分配 strchr 的返回值。 这是一个错误还是我只是错过了什么?在这两种情况下,生成的程序都按我预期的方式工作。

c gcc gcc-warning
2个回答
2
投票

在这个子表达式中:

(tmp = strchr(mode, 'b') != NULL)

不等式运算符

!=
的优先级高于赋值运算符
=
。所以上面等价于:

(tmp = (strchr(mode, 'b') != NULL))

这意味着您正在分配比较的结果,其类型为

int
并产生值0或1,并将其分配给
char *
,这就是您收到警告的原因。

需要先加括号才能进行赋值:

((tmp = strchr(mode, 'b')) != NULL)

1
投票

问题被黑之前

编译器看到:

if ((tmp = strchr(mode, 'b') != NULL) && tmp - mode < 3) return BINARY_MODE;

你声称你有:

if ((tmp = strchr(mode, 'b')) != NULL && tmp - mode < 3) return BINARY_MODE;

注意在

)
'b'
之后的右括号
NULL
数量上的差异。你声称你得到的是正确的代码——现在你需要确保这是编译器看到的。

问题被黑后

编译器仍然看到错误的代码,但你现在承认你给了它错误的代码。

那段代码相当于写:

if ((tmp = (strchr(mode, 'b') != NULL)) && tmp - mode < 3) return BINARY_MODE;

将比较结果分配给

tmp
——将
int
分配给
char *
,因为编译器在错误消息中抱怨。

正确的密码是您最初声称拥有的密码。您需要确保赋值与 null 进行比较,而不是调用

strchr()
.

的结果

所以,解决方法是写:

if ((tmp = strchr(mode, 'b')) != NULL && tmp - mode < 3) return BINARY_MODE;

代码“似乎”起作用了,因为您将

0
1
分配给了
tmp
,然后从中减去
mode
指针得到一个负的
ptrdiff_t
值,这是负的。我想你一定是在
b
存在的情况下进行了测试,而不是在
b
不存在的情况下进行了测试。

© www.soinside.com 2019 - 2024. All rights reserved.