2013-12-05 2 views
1

Например:Как перенести значение int64 в беззнаковое пространство int64 без изменения порядка?

  1. INT64_MIN до 0
  2. 0 до INT64_MAX + 1
  3. INT64_MAX в UINT64_MAX

Ниже мой код:

uint64_t int64ToUint64(int64_t value) 
{ 
    uint64_t uvalue = value - std::numeric_limits<int64_t>::min(); 
    return uvalue; 
} 

Он работает, но существует знаковое целочисленное переполнение, а для каждого стандарта C++ целочисленное переполнение целых чисел - это поведение undefin редактор Любые другие решения без полного переполнения?

+0

Насколько он вам нужен? Я уверен, что «подписанное переполнение» не определено по двум причинам: 1. Риск переполнения ловушек (в большинстве случаев это не проблема), 2. Дополнение дополняет друг друга -> наличие/отсутствие отрицательного нуля -> неопределенность какой битовой диаграммы приводит к тому, что значение. Если вас интересуют только «обычные» процессоры, такие как x86, ARM, 68K, 29K, MIPS, я бы сказал, что это «безопасно» (если MIPS сказано не генерировать переполненные ловушки) –

+0

@MatsPetersson на самом деле мы только на x86 RHEL6. Просто любопытно, есть ли лучшее решение. – bydsky

+0

Я не уверен, есть ли определенное решение. Возможно, преобразование в unsigned сначала, а затем вычитание смещения в качестве значения без знака было бы более надежным (но я не уверен, что это хорошо определено для значений, которые находятся за пределами 0..INT64_MAX. –

ответ

3

С переходом от подписана беззнаковых типов хорошо определен и, поскольку нет переполнения на неподписанной арифметике, вы можете делать то, что вы хотите безопасно сначала преобразовать подписанное значение без знака типа:

uint64_t int64ToUint64(int64_t value) 
{ 
    uint64_t uvalue = value; 

    uvalue += INT64_MAX; 
    uvalue += 1; 

    return uvalue; 
} 
+0

Cool. Как насчет преобразования uint64 в int64? – bydsky

-2
uint64_t int64ToUint64(int64_t value){ 
    uint64_t res = *(reinterpret_cast<uint64_t*>(&value)); 
    return res^numeric_limits<int64_t>::min(); 
} 
int64_t uint64ToInt64(uint64_t value){ 
    value ^= numeric_limits<int64_t>::min(); 
    return *(reinterpret_cast<int64_t*>(&value)); 
} 
+0

Целью было избегать неопределенного поведения. Кроме того, это нарушает порядок : 'int64ToUint64 (-1)> int64ToUint64 (0)'. – MSalters

+0

Я не понял вопрос правильно. Я думал о порядке бит. Итак, я скорректировал код. – weisert

+0

Я думаю, что он по-прежнему сломан для своего дополнения, но это теоретически. Боюсь, что 'reinterpret_cast' все еще UB. – MSalters

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

  • Нет связанных вопросов^_^