Reputation: 2320
I have a sample function as below:
int get_hash (unsigned char* str)
{
int hash = (str[3]^str[4]^str[5]) % MAX;
int hashVal = arr[hash];
return hashVal;
}
Here array arr has size as MAX. ( int arr[MAX]
).
My static code checker complains that there can be a out of bound array access here, as hash could be in the range -255 to -1.
Is this correct? Can bitwise operation on unsigned char produce a negative number? Should hash be declared as unsigned int?
Upvotes: 1
Views: 6961
Reputation: 183873
Is this correct?
No, the static code checker is in error(1).
Can bitwise operation on unsigned char produce a negative number?
Some bitwise operations can - bitwise complement, for example - but not the exclusive or.
For the ^
, the arguments, unsigned char
here, are subject to the usual arithmetic conversions (6.3.1.8), they are first promoted according to the integer promotions; about those, clause 6.3.1.1, paragraph 2 says
If an
int
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions.
So, there are two possibilities:
An int
can represent all possible values of unsigned char
. Then all values obtained from the integer promotions are non-negative, the bitwise exclusive or of these values is also non-negative, and the remainder modulo MAX
too. The value of hash
is then in the range from 0 (inclusive) to MAX
(exclusive) [-MAX
if MAX < 0
].
An int
cannot represent all possible values of unsigned char
. Then the values are promoted to type unsigned int
, and the bitwise operations are carried out at that type. The result is of course non-negative, and the remainder modulo MAX
will be non-negative too. However, in that case, the assignment to int hash
might convert an out-of-range value to a negative value [the conversion of out-of-range integers to a signed integer type is implementation-defined]. (1)But in that case, the range of possible negative values is greater than -255
to -1
, so even in that - very unlikely - case, the static code checker is wrong in part.
Should hash be declared as
unsigned int
?
That depends on the value of MAX
. If there is the slightest possibility that a remainder modulo MAX
is out-of-range for int
, then that would be safer. Otherwise, int
is equally safe.
Upvotes: 4
Reputation: 78903
As remarked correctly by gx_, the arithmetic is done in int
. Just declare your hash
variable as unsigned char
, again, to be sure that everybody knows that you expect this to be positive in all cases.
And if MAX
is effectively UCHAR_MAX
you should just use that to improve readability.
Upvotes: 1