How to represent negative char values ​​in hexadecimal format?

Following code

char buffer[BSIZE]; ... if(buffer[0]==0xef) ... 

Provides a compiler warning "Comparison is always incorrect due to a limited range of data types." The warning disappears when I change the check to

 if(buffer[0]==0xffffffef) 

This seems very controversial. What is the correct way to check char for a specific byte value in hex? (except for creating unsigned text)

0
source share
5 answers

To understand why buffer[0] == 0xef triggers a warning, but buffer[0] == 0xffffffef does not, you need to understand exactly what is going on in this expression.

Firstly, the == operator compares the value of two expressions, and not the basic representation - 0xef is the number 239 and will only be compared with that number; Similarly, 0xffffffef is the number 4294967279 and will only be compared with that.

There is no difference between the constants 0xef and 239 in C: both are of type int and have the same value. If your char has a range from -128 to 127, then when you evaluate buffer[0] == 0xef , buffer[0] gets the value int , which leaves its value unchanged. Therefore, it will never compare with 0xef , so the warning is correct.

However, there is a potential difference between the constants 0xffffffef and 4294967279; decimal constants are always signed, but the hexadecimal constant may be unsigned. On your system, it has an unsigned type β€” perhaps unsigned int (because the value is too large to store in int , but small enough to store it in unsigned int ). When you evaluate buffer[0] == 0xffffffef , buffer[0] advances to unsigned int . This leaves any positive value unchanged, but negative values ​​are converted by adding UINT_MAX + 1 to them; with char , which has a range from -128 to 127, advanced values ​​are in any range from 0 to 127 or from 4294967168 to 4294967295. 0xffffffef is in this range, so true can be returned for comparison.


If you store bit patterns, not numbers, you should use unsigned char in the first place. In addition, you can check the bit pattern of an object by pointing to it with an unsigned char * pointer:

 if (((unsigned char *)buffer)[0] == 0xef) 

(This is obviously more convenient to do using a separate variable of type unsigned char * ).

As PaulR says, you can also use buffer[0] == '\xef' - this works because '\xef' is defined as an int constant with the value that a char object with the 0xef bitmap will take place when converting to int ; eg. on a 2s complement system with signed characters, '\xef' is a constant with a value of -17.

+4
source

What happened with:

 if (buffer[0] == '\xef') 

?

+6
source

This is because the contents of buffer is of type char . Creating their unsigned char will work:

 if ((unsigned char) (buffer[0]) == 0xef) 
+3
source

Do this as with any other negative number:

 if (buffer[0]== -0x6f) 

But usually you want to use unsigned char as a data type:

 unsigned char buffer[BSIZE]; ... if(buffer[0]==0xef) 

Reasons to use a signed char are very rare. Even less commonly, you can use "char without a character specification", which can be signed or unsigned on different platforms.

+2
source

To clearly explain the reason: whether char signed or unsigned, an implementation is defined. If your compiler considers char be signed by default, then 0xef will be greater than the largest possible signed char (which is 127 or 0x7f ), and therefore your comparison will always be false. Hence the warning.

Possible solutions are provided by other answers.

+2
source

Source: https://habr.com/ru/post/1394271/


All Articles