m.divya.mohan
m.divya.mohan

Reputation: 2320

Bitwise operation on unsigned char

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

Answers (2)

Daniel Fischer
Daniel Fischer

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 an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.

So, there are two possibilities:

  1. 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].

  2. 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

Jens Gustedt
Jens Gustedt

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

Related Questions