C 如何用十六进制表示负字符值?

C 如何用十六进制表示负字符值?,c,char,hex,signedness,C,Char,Hex,Signedness,下面的代码 char buffer[BSIZE]; ... if(buffer[0]==0xef) ... 给出编译器警告“由于数据类型范围有限,比较总是错误的”。 当我把支票换成现金时,警告就消失了 if(buffer[0]==0xffffffef) 这感觉很违反直觉。根据十六进制中的特定字节值检查字符的正确方法是什么?(除了取消签名)有什么问题: if (buffer[0] == '\xef') ?发生这种情况是因为缓冲区内容的类型为字符。使它们无符号字符将起作用: if ((unsi

下面的代码

char buffer[BSIZE];
...
if(buffer[0]==0xef)
...
给出编译器警告“由于数据类型范围有限,比较总是错误的”。 当我把支票换成现金时,警告就消失了

if(buffer[0]==0xffffffef)
这感觉很违反直觉。根据十六进制中的特定字节值检查字符的正确方法是什么?(除了取消签名)

有什么问题:

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

发生这种情况是因为
缓冲区
内容的类型为
字符
。使它们
无符号字符
将起作用:

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

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

if (buffer[0]== -0x6f)
但通常您希望使用无符号字符作为数据类型:

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

使用有符号字符的原因很少。更为罕见的是使用“无符号字符规范”的原因,它可以在不同的平台上进行签名或不签名。

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


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

要理解为什么
buffer[0]==0xef
触发警告,而
buffer[0]==0xffffef
不触发警告,您需要准确理解该表达式中发生了什么

首先,
=
运算符比较两个表达式的值,而不是底层表示-
0xef
是数字239,并且只比较等于该数字的值;同样地,
0xffffff
是数字4294967279,并且将仅与该数字进行比较

C中的常量
0xef
239
之间没有区别:它们都有type
int
和相同的值。如果
char
的范围为-128到127,那么当您计算
buffer[0]==0xef
时,
buffer[0]
将升级为
int
,其值保持不变。因此,它永远无法比较等于
0xef
,因此警告是正确的

然而,常数
0xffffff
和4294967279之间可能存在差异;十进制常量总是有符号的,但十六进制常量可能没有符号。在您的系统上,它似乎具有无符号类型-可能是
无符号int
(因为该值太大,无法存储在
int
中,但太小,无法存储在
无符号int
中)。当您计算
缓冲区[0]==0xffffffef
时,
缓冲区[0]
将升级为
无符号int
。这使得任何正值保持不变,但负值通过向其添加
UINT_MAX+1
进行转换;对于范围为-128到127的
char
,提升的值在0到127或4294967168到4294967295之间
0xFFFFFF
位于该范围内,因此比较可能返回true


如果存储的是位模式而不是数字,那么首先应该使用
无符号字符
。或者,您可以通过将指向对象的指针投射到
无符号字符*
,来检查对象的位模式:

if (((unsigned char *)buffer)[0] == 0xef)
(使用类型为
unsigned char*
的单独变量显然更方便)


如上所述,您还可以使用
缓冲区[0]='\xef'
——这是因为
'\xef'
被定义为
int
常量,其值是位模式为0xef的
char
对象在转换为int时的值;例如,在带符号字符的2s补码系统上,
'\xef'
是一个值为-17的常数。

这似乎是错误的-我猜你可能尝试了
if(buffer='\xef')
而不是
if(buffer[0]='\xef')
。哎呀,我刚才说的是如果(buffer[0]='\xef')。这是一个很好的答案——buffer是一个字符数组,所以你应该把它比作一个字符。实际上,我用这个答案来解决我的问题,但因为详细的解释,我接受了另一个答案。非常感谢。谢谢你的详细解释。我的代码处理字符串和可能的UTF-8。很好的解释。总而言之,两个不同长度的兼容基准之间的关系始终在最长基准的上下文中执行。在评估之前,较短的数据将通过符号/零扩展转换为较长的类型,以分别保持其相关的有符号/无符号范围。