为什么'\ xff'不被识别?

时间:2014-05-23 00:54:29

标签: c

我知道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。

3 个答案:

答案 0 :(得分:4)

如果您有未签名的,则不能使用字符文字。

'\ xff'是-1而不是255,因为字符文字已签名。

while条件始终为真。如果你是未签名的,你应该只使用数字:0到255,或者你知道的铸造字符< 128到无符号。

答案 1 :(得分:4)

\xff是一个字符常量。它的类型为int,而不是char(这是C与C ++不同的一种方式),但其值取决于普通char是有符号还是无符号,是实现定义的。

C标准中的措辞是:

  

反斜杠后面的十六进制数字和字母 x   十六进制转义序列被视为构造的一部分   单个字符的整数字符常量或单个字符   宽字符常数。的数值   这样形成的十六进制整数指定了所需的值   性格或广泛的性格。

如果普通char未签名,则'\xff'相当于0xff255;它的类型为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'