为什么数组中的 char 在 gcc 中为 newlib 中的 isspace 给出下标警告
Why is does char from an array give subscript warning in gcc for isspace in newlib
我无法理解代码中的编译器警告。我们的代码与本例中给出警告 (-Wchar-subscripts) 的代码类似。我们使用 ARM gcc 9.2.1 embedded 和 newlib 作为标准库。
#include <ctype.h>
int main ()
{
char str[]="Example string\n";
int i = isspace(str[1]); // Warning
char c=str[1];
i = isspace(c); // No warning
i = isspace((unsigned char)str[1]); // No warning
}
据我了解,isspace 的实现可以通过数组索引。因此警告。但在那种情况下,1 和 2 不应该都发出警告吗?为什么只有第一个发出警告?
我们通过添加强制转换解决了我们的代码,但在我理解它为什么有用之前我并不真正满意。
这似乎与此处 Bugzilla 中讨论的错误完全相同 Bug 95177 - error: array subscript has type char。基本上 gcc 的诊断不一致,这种行为只出现在以后的版本中。
正如该线程中所讨论的那样,将 char
传递给 ctype.h 函数理论上可能会出现问题,以防 char
包含任何未知内容。这些函数被定义为期望输入可以表示为 unsigned char
,参见 C17 7.4:
In all cases the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of the macro EOF
因此 int i = isspace((unsigned char)str[1]);
使警告消失。
但正如您所见,警告是不一致的。这可能是因为当您使用 ctype.h 时,编译器有时会选择一个宏,有时会选择一个函数。
就把它禁用掉,当成误报。根据上面的 Bugzilla 日志,这个问题最近应该已经修复了。 gcc (trunk) 和 gcc >10.3 不再给出此警告。
isspace(str[1])
和 isspace(c)
之间的警告消息差异是由 GCC 抑制系统 headers 警告消息的功能中的错误引起的。
考虑这段代码:
#include <ctype.h>
int foo(char c)
{
return isspace(c);
}
int bar(char c)
{
return
((((_ctype_)+sizeof(""[
c
]))[(int)(
c
)])&010);
}
bar
中的代码是对foo
中的代码进行宏替换的结果(用-E
编译得到,以显示预处理结果)。所以这两个函数在宏替换后具有相同的代码,并且应该具有相同的语义。然而the second code gets a warning and the first code does not。因此,GCC 的报告并不仅仅基于代码的 C 语义。
GCC 具有抑制系统 header 文件中的警告的功能。当禁用此功能时(通过使用 -Wsystem-headers
),两个函数都会收到一条警告消息。因此,isspace(str[1])
而不是 isspace(c)
出现的警告是由于系统 headers 中抑制警告消息的功能失败。也就是说,它是 GCC 中的一个错误。
为了确认,将 -Wsystem-headers
与问题中的原始代码一起使用会产生 warning messages for both isspace(str[1])
and isspace(c)
。
我无法理解代码中的编译器警告。我们的代码与本例中给出警告 (-Wchar-subscripts) 的代码类似。我们使用 ARM gcc 9.2.1 embedded 和 newlib 作为标准库。
#include <ctype.h>
int main ()
{
char str[]="Example string\n";
int i = isspace(str[1]); // Warning
char c=str[1];
i = isspace(c); // No warning
i = isspace((unsigned char)str[1]); // No warning
}
据我了解,isspace 的实现可以通过数组索引。因此警告。但在那种情况下,1 和 2 不应该都发出警告吗?为什么只有第一个发出警告?
我们通过添加强制转换解决了我们的代码,但在我理解它为什么有用之前我并不真正满意。
这似乎与此处 Bugzilla 中讨论的错误完全相同 Bug 95177 - error: array subscript has type char。基本上 gcc 的诊断不一致,这种行为只出现在以后的版本中。
正如该线程中所讨论的那样,将 char
传递给 ctype.h 函数理论上可能会出现问题,以防 char
包含任何未知内容。这些函数被定义为期望输入可以表示为 unsigned char
,参见 C17 7.4:
In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF
因此 int i = isspace((unsigned char)str[1]);
使警告消失。
但正如您所见,警告是不一致的。这可能是因为当您使用 ctype.h 时,编译器有时会选择一个宏,有时会选择一个函数。
就把它禁用掉,当成误报。根据上面的 Bugzilla 日志,这个问题最近应该已经修复了。 gcc (trunk) 和 gcc >10.3 不再给出此警告。
isspace(str[1])
和 isspace(c)
之间的警告消息差异是由 GCC 抑制系统 headers 警告消息的功能中的错误引起的。
考虑这段代码:
#include <ctype.h>
int foo(char c)
{
return isspace(c);
}
int bar(char c)
{
return
((((_ctype_)+sizeof(""[
c
]))[(int)(
c
)])&010);
}
bar
中的代码是对foo
中的代码进行宏替换的结果(用-E
编译得到,以显示预处理结果)。所以这两个函数在宏替换后具有相同的代码,并且应该具有相同的语义。然而the second code gets a warning and the first code does not。因此,GCC 的报告并不仅仅基于代码的 C 语义。
GCC 具有抑制系统 header 文件中的警告的功能。当禁用此功能时(通过使用 -Wsystem-headers
),两个函数都会收到一条警告消息。因此,isspace(str[1])
而不是 isspace(c)
出现的警告是由于系统 headers 中抑制警告消息的功能失败。也就是说,它是 GCC 中的一个错误。
为了确认,将 -Wsystem-headers
与问题中的原始代码一起使用会产生 warning messages for both isspace(str[1])
and isspace(c)
。