如何以十六进制表示负 char 值?

发布于 2024-11-19 13:02:57 字数 266 浏览 3 评论 0原文

以下代码

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

向编译器发出警告“由于数据类型范围有限,比较始终为假”。 当我将检查更改为

if(buffer[0]==0xffffffef)

“这感觉非常违反直觉”时,警告就会消失。根据十六进制的特定字节值检查 char 的正确方法是什么? (除了使其未签名之外)

The following code

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

Gives the compiler warning "comparison is always false due to limited range of data type".
The warning goes away when I change the check to

if(buffer[0]==0xffffffef)

This feels very counterintuitive. What is the correct way to check a char against a specific byte value in hex? (other than making it unsigned)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

笔落惊风雨 2024-11-26 13:02:57

有什么问题:

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

What's wrong with:

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

?

就像说晚安 2024-11-26 13:02:57

要了解为什么 buffer[0] == 0xef 会触发警告,而 buffer[0] == 0xffffffef 不会触发警告,您需要准确了解该表达式中发生的情况。

首先,== 运算符比较两个表达式的,而不是底层表示 - 0xef 是数字 239,并且只会比较相等到那个号码;同样,0xffffffef 是数字 4294967279,并且只会比较等于该数字。

C 中的常量 0xef239 没有区别:两者都具有 int 类型和相同的值。如果您的 char 范围为 -128 到 127,那么当您评估 buffer[0] == 0xef 时,buffer[0] 会被提升为 int,其值保持不变。因此,它永远不能与 0xef 进行比较,因此警告是正确的。

但是,常量 0xffffffef 和 4294967279 之间可能存在差异;十进制常量总是有符号的,但十六进制常量可能是无符号的。在您的系统上,它似乎有一个无符号类型 - 可能是 unsigned int (因为该值太大而无法存储在 int 中,但又足够小,可以存储在 <代码>无符号整数)。当您计算 buffer[0] == 0xffffffef 时,buffer[0] 将提升为 unsigned int。这将保持任何正值不变,但通过向负值添加 UINT_MAX + 1 来转换负值;对于范围为 -128 到 127 的 char,提升的值范围为 0 到 127 或 4294967168 到 4294967295。0xffffffef 位于此范围内,因此它比较有可能返回 true。


如果您要存储位模式而不是数字,那么您应该首先使用unsigned char。或者,您可以通过将指向对象的指针强制转换为 unsigned char * 来检查对象的位模式:(

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

这显然通过使用 unsigned char *< 类型的单独变量来更方便地完成/代码>)。

正如 PaulR 所说,您可以还可以使用 buffer[0] == '\xef' - 这有效,因为 '\xef' 被定义为int 常量,其值是位模式为 0xef 的 char 对象转换为 int 时所具有的值;例如。在带有符号字符的 2 补码系统上,'\xef' 是值为 -17 的常量。

To understand why buffer[0] == 0xef triggers a warning, and buffer[0] == 0xffffffef does not, you need to understand exactly what's happening in that expression.

Firstly, the == operator compares the value of two expressions, not the underlying representation - 0xef is the number 239, and will only compare equal to that number; likewise 0xffffffef is the number 4294967279 and will only compare equal to that.

There is no difference between the constants 0xef and 239 in C: both have type int and the same value. If your char has the range -128 to 127, then when you evaluate buffer[0] == 0xef the buffer[0] is promoted to int, which leaves its value unchanged. It can therefore never compare equal to 0xef, so the warning is correct.

However, there is potentially a difference between the constants 0xffffffef and 4294967279; decimal constants are always signed, but hexadecimal constant may be unsigned. On your system, it appears to have an unsigned type - probably unsigned int (because the value is too large to store in an int, but small enough to store in an unsigned int). When you evaluate buffer[0] == 0xffffffef, the buffer[0] is promoted to unsigned int. This leaves any positive value unchanged, but negative values are converted by adding UINT_MAX + 1 to them; with a char that has range -128 to 127, the promoted values are in either of the ranges 0 to 127 or 4294967168 to 4294967295. 0xffffffef lies within this range, so it is possible for the comparison to return true.


If you are storing bit patterns rather than numbers, then you should be using unsigned char in the first place. Alternatively, you may inspect the bit pattern of an object by casting a pointer to it to unsigned char *:

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

(This is obviously more conveniently done by using a separate variable of type unsigned char *).

As PaulR says, you can also use buffer[0] == '\xef' - this works because '\xef' is defined to be an int constant with the value that a char object with the bit pattern 0xef would have when converted to an int; eg. on a 2s complement system with signed chars, '\xef' is a constant with the value -17.

初雪 2024-11-26 13:02:57

发生这种情况是因为 buffer 内容的类型为 char。让它们成为 unsigned char 就可以了:

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

This is happening because buffer contents are of type char. Making them unsigned char will work:

if ((unsigned char) (buffer[0]) == 0xef)
沦落红尘 2024-11-26 13:02:57

就像处理任何其他负数一样:

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

但通常您希望使用 unsigned char 作为数据类型:

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

使用signed char 的原因非常罕见。更罕见的是使用“无符号规范的字符”的原因,它可以在不同的平台上进行签名或未签名。

Do it just like with any other negative number:

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

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

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

Reasons to use signed char are very rare. Even more rare are reasons to use "char without sign specification", which can be signed or unsigned on different platforms.

笑饮青盏花 2024-11-26 13:02:57

明确说明原因:char 是有符号还是无符号是实现定义的。如果您的编译器默认将 char 视为有符号,则 0xef 将大于可能的最大 signed char(即 127 或 0x7f),因此你的比较将始终是错误的。因此发出警告。

其他答案提供了可能的解决方案。

To spell out the reason explicitly: Whether char is signed or unsigned is implementation defined. If your compiler treats char as signed by default then 0xef will be larger than the largest possibled signed char (which is 127 or 0x7f) and therefore your compare will always be false. Hence the warning.

Possible solutions are provided by the other answers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文