2016-12-08 4 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 (строка «привет»). Поэтому он должен быть 0x82> = 0x80, как в true, и возвращать байты, но по какой-то причине это сравнение получает false и возвращает char * нормальной строки, что, конечно же, является фиктивным указателем (точнее, 0xcc006968).

Также стоит отметить, что этот код по-прежнему работает правильно для обычных строк.

Что мне не хватает, что я делаю неправильно?

+5

Поскольку 0x80 является отрицательным символом (помните, что тип символа подписан, по крайней мере, на вашей платформе). –

+0

Можете ли вы опубликовать полный, минимальный, проверенный пример? Поведение, которое вы описываете, довольно странно. – templatetypedef

ответ

7

Значение 0x80 отрицательное число при использовании подписал 8-битные целые. Таким образом, 0x82 будет меньше, потому что это также отрицательно. Значение 0x82 переводит на -126, а 0x80 переводит на -128, что означает, что 0x80 меньше 0x82 в двухзначных числах со знаком со знаком.

Включите ваши данные, используя uint8_t.

+0

@Nikita: конвертировать шестнадцатеричные значения 0x80 и 0x82 в дополнение к представлению двойного представления, предполагая 8-битное количество и посмотреть, переполняется ли он. –

+1

Возможно, я действительно тупой, но не 0x80 = -128 и 0x82 = -126? Итак, 0x80 все равно будет меньше 0x82? Принимая это в крайнем случае, 0xFF будет равным -1 и 0x80 <0xFF. – templatetypedef

+0

@templatetypedef: Плохо, ты прав. Я отредактирую свой ответ. Благодарю. –

2

символ * подписан 0x80 и за ее пределами отрицательны

+1

Тип 'char' может быть' char', 'signed char' или' unsigned char', в зависимости от настроек компилятора. –

+2

Только садист изменит знак char с настройкой компилятора. – 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) к подписанному междунару (0x00000080 = 128). Подписанный символ может быть числом от -128 до 127, поэтому он всегда будет меньше 128.

Смежные вопросы