我知道0xff可以有不同的表示形式,具体取决于变量类型。对于有符号(chars / ints(?)),则为-1,对于无符号的字符,则为255.
但是我使用的是与实现无关的uint8_t类型,我已经确保0xff在我迭代的结构中。这是代码:
struct pkt {
uint8_t msg[8];
};
void main(int argc, char **argv) {
...
struct pkt packet;
memset(&packet, 0, sizeof packet);
strcpy(packet.msg, "hello");
packet.msg[strlen("hello")] = '\xff';
crypt(&packet, argv[1]);
...
}
void crypt(struct pkt *packet, unsigned char *key) {
int size = msglen(packet->msg);
...
}
int msglen(uint8_t *msg) {
int i = 0;
while(*(msg++) != '\xff') {
i++;
}
return i;
}
我查看了结构,并且packet.msg [5]确实设置为0xff。但是while循环进入无限循环,就像它从未发现过0xff一样。
诸如0x7f之类的值有效。我没有尝试过0x80,但我怀疑如果0xff没有,它可能无效。它可能与符号有关,但我无法确定问题应该来自何处。
感谢。
编辑:对我来说,如果我使用0x7f或0xff并不重要。但我想知道是什么阻止我检测到0xff。
答案 0 :(得分:4)
如果您有未签名的,则不能使用字符文字。
'\ xff'是-1而不是255,因为字符文字已签名。
while条件始终为真。如果你是未签名的,你应该只使用数字:0到255,或者你知道的铸造字符< 128到无符号。
答案 1 :(得分:4)
\xff
是一个字符常量。它的类型为int
,而不是char
(这是C与C ++不同的一种方式),但其值取决于普通char
是有符号还是无符号,是实现定义的。
C标准中的措辞是:
反斜杠后面的十六进制数字和字母
x
十六进制转义序列被视为构造的一部分 单个字符的整数字符常量或单个字符 宽字符常数。的数值 这样形成的十六进制整数指定了所需的值 性格或广泛的性格。
如果普通char
未签名,则'\xff'
相当于0xff
或255
;它的类型为int
,其值为255
。
如果明文char
已签名,则'\xff'
指定的值超出char
范围(假设char
为8位)。标准的措辞对我来说不是100%清楚,但至少对于gcc,'\xff'
的值是-1
。
只使用整数常量0xff
而不是字符常量\xff'
。 0xff
的类型为int
,并且保证其值为255
,这就是您想要的。
答案 2 :(得分:2)
我知道0xff可以有不同的表示形式,具体取决于变量类型。对于有符号(chars / ints(?)),则为-1,对于无符号的字符,则为255.
这需要一些解释。 C程序中的整数文字0xFF
始终表示255
。如果您将此分配给255
超出范围的类型,例如a signed char
然后行为是实现定义的。通常在2的补码系统上,这被定义为赋值-1
。
字符文字对整数文字有不同的规则。字符文字'\xff'
必须是可以位于char
的值。您似乎签署了char
,因此它的实现定义了此处发生的事情,但最常见的行为是,它获得了值-1
。请注意,字符文字实际上具有类型int
,尽管它们必须具有char
可表示的值。
在packet.msg[strlen("hello")] = '\xff';
行中,您尝试将(int)-1
分配给uint8_t
。这超出了范围,但是对于已签名类型的超出范围分配,行为已明确定义,因此您获得的值为-1 (mod 256)
,即255
。
最后,当使用==
运算符(和大多数运算符)时,如果值不是int,则值将提升为int
。 8位整数255
被提升为(int)255
,您将其与(int)-1
进行比较,它们会有所不同。
要解决此问题,请将您的比较更改为0xFF
或(uint8_t)'\xFF'
。