我在C中有以下代码:
char input[127] = "hello world";
isxdigit(input[0]);
但是我收到了以下警告:
warning: array subscript has type 'char'
是什么原因以及如何解决?
答案 0 :(得分:8)
原因是在您的C实现中,使用数组查找将isxdigit()
实现为宏。
只要您的输入字符串仅包含字符< = 127,您就可以使用强制转换来修复它:
isxdigit ((int)input[0]);
或者,如果您认为演员阵容很丑陋,可以借助良性表达,例如添加0:
isxdigit (0 + input[0]); /* Avoid cast by using an int-typed expression. */
isxdigit (+input[0]); /* Same thing using unary plus instead of addition. */
由于C标准要求isxdigit
也是一个函数,你也可以调用函数而不是宏:
(isxdigit)(input[0]);
甚至
#undef isxdigit
isxdigit(input[0]);
这不会产生任何警告,因为input[0]
被提升为int
(假设之前是#include <ctype.h>
。)
正如cmaster正确指出的那样,一旦您的char
签名并包含负值,这些解决方案就会崩溃。在这种情况下,您必须首先投射到unsigned char
(如果需要,则转到int
。)
答案 1 :(得分:2)
原因是isxdigit
有原型int isxdigit(int)
。因此,要删除此警告,您应该明确地将参数强制转换为int
isxdigit((int)input[0]);
答案 2 :(得分:2)
关键是,标准没有定义char类型是否已签名,而是将此决定留给实现。因此(int)(char)128
可以评估为128或-128。后者显然不适合数组索引,因为你的编译器注意到了(聪明人,编译器)。
因此,正确的解决方法是投放到unsigned char
,而不是投放到int
。
isxdigit((unsigned char)input[0])
如果你选择其他错误的答案,你最终可能会崩溃utf8字符串! (对于多字节字符,utf8使用大于127的代码。)
编辑:当然,Pascal Cuoq说的是,这样的实现不允许将isxdigit实现为表查找宏,但是,我所说的适用于此编译器警告的任何出现,包括任何查找表你自己实施。非常不幸的是,char的签名没有定义,人们应该更好地了解这个问题并且知道要正确地避免它。