Подтвердить что ты не робот

Как вы определяете 64-битный unsigned int const 0x8000000000000000 в VS2008?

Я читал о специфическом суффиксе Microsoft "i64" для целочисленных констант. Я хочу сделать сдвиг без изменений в ULONGLONG.
ULONGLONG bigNum64 = 0x800000000000000i64 >> myval;

В нормальном C я бы использовал суффикс "U", например. аналогичная 32-битная операция будет ULONG bigNum32 = 0x80000000U >> myval;

Я НЕ хочу, чтобы расширение расширения 2-го дополнения распространялось через высокие бит. Я хочу сдвиг UNSIGNED на 64-битном const-номере. Я думаю, что мое первое утверждение будет делать правый SIGNED.

Я пробовал 0x800000000000000i64U и 0x800000000000000u64, но получил ошибки компилятора.

4b9b3361

Ответ 1

Вы можете использовать суффикс ull, который является стандартным (C99 и С++ 0x) способом для указания целочисленного литерала unsigned long long, а long long - не менее 64 бит.

Ответ 2

Забавно, но на самом деле вам не нужно добавлять какой-либо суффикс в свою шестую константу, чтобы он правильно обрабатывался. Раздел 6.4.4.1 стандарта C и раздел 2.14.3 стандарта С++ содержат следующую таблицу:

Suffix       | Decimal Constant       | Octal or Hexadecimal Constant
-------------+------------------------+------------------------------
none         | int                    | int
             | long int               | unsigned int
             | long long int          | long int
             |                        | unsigned long int
             |                        | long long int
             |                        | unsigned long long int
-------------+------------------------+------------------------------
u or U       | unsigned int           | unsigned int
             | unsigned long int      | unsigned long int
             | unsigned long long int | unsigned long long int
-------------+------------------------+------------------------------
l or L       | long int               | long int
             | long long int          | unsigned long int
             |                        | long long int
             |                        | unsigned long long int
-------------+------------------------+------------------------------
Both u or U  | unsigned long int      | unsigned long int
and l or L   | unsigned long long int | unsigned long long int
-------------+------------------------+------------------------------
ll or LL     | long long int          | long long int
             |                        | unsigned long long int
-------------+------------------------+------------------------------
Both u or U  | unsigned long long int | unsigned long long int
and ll or LL |                        |

В этой таблице указывается, какой тип будет иметь целочисленная константа. Тип целочисленного константы будет первым типом, в котором оно соответствует значению.

Это означает, что компилятор будет перебирать следующие типы для шестнадцатеричной константы 0x800000000000000 (у нее нет суффикса, поэтому она использует строку "none", и она является шестнадцатеричной константой, поэтому использует "шестнадцатеричную константу", столбец), и он будет использовать первый тип, который может сохранить это значение *:

  • int: Нет, 32-разрядное целое со знаком не может сохранить это значение.
  • unsigned int: Нет, 32-разрядное целое число без знака не может сохранить это значение.
  • long int: Нет, 32-разрядное целое со знаком не может сохранить это значение.
  • unsigned long int: Нет, 32-разрядное целое число без знака не может сохранить это значение.
  • long long int: Нет, 64-разрядное целое со знаком не может сохранить это значение.
  • unsigned long long int. Да, это 64-разрядное целое без знака может сохранить это значение. Так как это первый тип, который может полностью сохранить значение, это тип, который будет иметь константа целого.

Итак, чтобы ответить на ваш вопрос "Как написать и использовать значение 0x800000000000000 и убедиться, что компилятор не будет обрабатывать высокий бит как знаковый бит?": просто напишите unsigned long long value = 0x800000000000000.

Если вы хотите выполнить некоторую побитовую арифметику со значением, вы можете просто пойти вперед и сделать это (т.е. просто написать 0x800000000000000 >> myval). Вам гарантировано, что он не будет рассматриваться как переполненное целое число со знаком, и ваш сдвиг вправо не будет делать никаких расширений знака, потому что это положительное значение.

* Я предполагаю, что int - 32-разрядный, long - 32-разрядный, а long long - 64-разрядный. Обратите внимание, что ваш компилятор может использовать разные типы бит для этих типов, что может изменить конечный результат (хотя процесс все равно будет таким же).

Ответ 3

Вот способ:

int main()
{
   uint64_t val1=0x1p63;  //1 * 2**63
   uint64_t val2=((uint64_t)0x1p63)-1;  //0x1p63 is a float constant 
   uint64_t val3= ((uint64_t)0x1p63) >> 2;
   cout << hex << "val1=" << val1 << " val2=" << val2 << " val3=" << val3 << endl;
   return 0;
}

val1 = 8000000000000000 val2 = 7fffffffffffffff val3 = 2000000000000000