我有一个示例函数如下:
int get_hash (unsigned char* str)
{
int hash = (str[3]^str[4]^str[5]) % MAX;
int hashVal = arr[hash];
return hashVal;
}
这里数组arr的大小为MAX。 (int arr[MAX]
)。
我的静态代码检查器抱怨这里可能存在一个超出绑定的数组访问,因为哈希可能在-255到-1的范围内。
这是对的吗?可以对unsigned char进行逐位运算产生负数吗? hash应该声明为unsigned int吗?
答案 0 :(得分:4)
这是对的吗?
不,静态代码检查器出错(1)。
对unsigned char的按位运算是否会产生负数?
某些按位运算可以 - 例如按位补码 - 但不包括异或。
对于^
,这里的参数unsigned char
遵循通常的算术转换(6.3.1.8),它们首先根据整数提升进行推广;关于这些,第6.3.1.1条,第2款说
如果
int
可以表示原始类型的所有值(受宽度限制,对于位字段),则该值将转换为int
;否则,它将转换为unsigned int
。这些被称为整数促销。
所以,有两种可能性:
int
可以代表unsigned char
的所有可能值。然后,从整数提升获得的所有值都是非负的,按位异或这些值也是非负的,其余的也是模MAX
。 hash
的值在0(包括)到MAX
(不包括){-MAX
MAX < 0
的范围内。
int
无法代表unsigned char
的所有可能值。然后将值提升为类型unsigned int
,并按该类型执行按位运算。结果当然是非负的,其余的模MAX
也是非负的。但是,在这种情况下,对int hash
的赋值可能会将超出范围的值转换为负值[超出范围的整数到有符号整数类型的转换是实现定义的]。 (1)但在这种情况下,可能的负值范围大于-255
到-1
,所以即使在那个 - 非常不可能 - 的情况下,静态代码检查器部分是错误的。
哈希应该声明为
unsigned int
吗?
这取决于MAX
的值。如果MAX
的余数模int
的余数最小可能超出范围,那么这将更安全。否则,int
同样安全。
答案 1 :(得分:1)
正如gx_正确评论的那样,算法是在int
中完成的。只需将hash
变量再次声明为unsigned char
,以确保每个人都知道您希望在所有情况下均为正值。
如果MAX
有效UCHAR_MAX
,您应该使用它来提高可读性。