2016-12-08 68 views
0

我正在尝试为大学课程练习优化一个String类。 正常字符串被存储为char *和size_t长度。 sizeof(String)是8,它应该保持这样。然而,如果我只有7个或更少字符的字符串(或6,如果你考虑空终止符),而不是使用指针,我想直接存储在指针/ size_t字节。为什么0x82小于0x80?

为此,我有两个结构体,一个用于char *和size_t,另一个用8个字符(字节)的数组构成。我都加入了一个工会,并且让这个String类成为这个工会的成员。

要确定一个字符串是一个正常的字符串还是一个短字符串,我使用长度为size_t或byte [7]的最高有效位。如果字节[7]大于或等于128(或0x80),则它是一个短字符串,字符直接存储在字节中。然后将该长度存储在字节[7]的其余位中。

这就是迄今为止的理论。正常的字符串位已经实现,我现在试图实现短字符串位。我现在的问题是与下面的代码位:

inline const char* c_str(void) const 
    { 
     if (compound.bytes.bytes[7] >= 0x80) 
      return compound.bytes.bytes; 
     return compound.string.m_string; 
    } 

从Visual Studio观察家我知道compound.bytes.bytes [7]为0x82(字符串为“HI”)。所以它应该是0x82> = 0x80,因为在true中并返回字节,但由于某些原因,此比较变为false,并返回正常字符串的char *,这当然是一个假指针(准确地说是0xcc006968)。

另外值得指出的是,这个非常正常的字符串仍然正常工作的代码。

我在想什么,我做错了什么?

+5

因为0x80是一个负数字符(记住,字符类型至少在您的平台上是有符号的)。 –

+0

你能发布一个完整的,最小的,可验证的例子吗?你描述的行为很奇怪。 – templatetypedef

回答

7

的值0x80表示负数使用符号的8位整数时。 因此0x82会更少,因为它也是负值。值0x82转换为-126,0x80转换为-128,这意味着0x80小于0x82 ,二进制补码有符号整数

将您的数据类型切换为uint8_t

+0

@Nikita:假设8位数量,将十六进制值0x80和0x82转换为二进制补码表示形式,并查看它是否溢出。 –

+1

也许我真的很笨,但不是0x80 = -128和0x82 = -126?那么0x80仍然会小于0x82?把它变得极端,0xFF将是-1,并且0x80 <0xFF。 – templatetypedef

+0

@templatetypedef:我不好,你说的没错。我会编辑我的答案。谢谢。 –

2

字符*签署0x80的及以后是负

+1

根据编译器设置,'char'类型可以是'char','signed char'或'unsigned char'。 –

+2

只有一个虐待者会用编译器设置来改变字符的符号。 – boatcoder

1

您正在使用有符号值(char)。所以,0x80表示-128,而0x82表示-126。此代码可能会按需要工作:

inline const char* c_str(void) const 
{ 
    if (static_cast<unsigned char>(compound.bytes.bytes[7]) >= 0x80u) 
     return compound.bytes.bytes; 
    return compound.string.m_string; 
} 
0

您正在比较带符号字符(0x82 = -126)与带符号int(0x00000080 = 128)。带符号的char可以是从-128到127的数字,所以它总是小于128.

相关问题