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

В С++, в чем разница между 1 и 1i64?

Я конвертирую 32-разрядный совместимый код в 64-разрядный - и я попал в ловушку. Я компилирую проект VS2008 x64, и я получаю это предупреждение:

warning C4334: '<<' : result of 32-bit shift implicitly converted to 64 bits
(was 64-bit shift intended?)

Здесь исходная строка кода:

if ((j & (1 << k)) != 0) {

И вот как это выглядит, если я следую Совету Microsoft:

if ((j & (1i64 << k)) != 0) {

Безопасно ли это делать, когда код будет скомпилирован как на 32-битной, так и на 64-разрядной системах? Если да, объясните, почему я должен добавить "i64" до конца и почему это не повлияет на 32-битную компиляцию. В противном случае будет полезно оценить работу.

Помимо этого, у меня есть то, что похоже на еще более сложную часть кода.

if (id[j] != id[j ^ (1u << k)]) {

Я понимаю, что "u" означает, что цифра неподписанна, но какая точка указывает, что на значение, которое не превышает подписанное максимальное значение... Я предполагаю, что это имеет какое-то отношение к бит сдвиг?

4b9b3361

Ответ 1

1 имеет тип int в соответствии со стандартом С++. В 64-разрядном компиляторе Microsoft int имеет sizeof = 4 байта, это означает, что int - это 32-битная переменная. 1i64 имеет тип __int64.

Когда вы используете оператор shift, тип результата совпадает с типом левого операнда. Это означает, что при переключении 1 вы получите 32-битный результат. Компилятор Microsoft предполагает, что это может быть не то, что вы ожидаете (на 64-битной платформе), и выдает предупреждающее сообщение.

При использовании результата 1i64 на обеих платформах будет 64-бит. j и 0 будут неявно переданы в 64-разрядные. Таким образом, все выражение будет вычисляться в 64-битных переменных, а результат будет bool.

Таким образом, использование 1i64 безопасно для обеих платформ (32/64).

Ответ 2

Суффикс i64 зависит от Microsoft. Чтобы быть более портативным (если вас это беспокоит), вы можете использовать макрос INT64_C() из stdint.h:

#include <stdint.h>

// ...

if ((j & (INT64_C( 1) << k)) != 0) { ... }

К сожалению, у MS нет stdint.h как части их библиотеки C (большинство других компиляторов, похоже, есть), но, к счастью, вы можете получить один из нескольких источников:

Теперь у вас будет 64-битная константа, которая будет работать с широким спектром компиляторов.

Насколько вам может понадобиться или нужно 64-битное значение, оно зависит от типов различных частей выражения. Было бы полезно знать типы id, j и k, чтобы иметь возможность ответить, нужен ли суффикс 'u для константы или нет, и какой эффект он может иметь.

Ответ 3

1i64 Я считаю, что это подписанное 64-битное целое число. Я не могу провозгласить какой-либо опыт в реализации Microsoft, но в GCC решение для поддержки 64-битных целых чисел на 32-битных процессорах должно было сделать длинными длинными двойными словами, используя структуры и различные макросы черной магии. Поэтому i64 должен быть совместимым.

Что касается последнего бита voodoo - единственная точка в определении 1u, это потому, что возможно, что если k достаточно велико, результат сдвига будет соответствовать/превышать 32 бит памяти, и в этом случае результат будут отличаться, если операнд LH обрабатывается как подписанное или целое число без знака.

Ответ 4

Так как этот код "и" 64-битная переменная j с результатом (32-разрядной) бит-сдвига, результат будет "расширен" до 64 бит компилятором.

Вероятно, вы хотите контролировать, как вычисляется второй операнд с 'и', поэтому компилятор предлагает вам использовать полные 64 бита, сделав первый операнд __int64. Это безопасно в 32 бит, но вы должны действительно посмотреть на тип j, чтобы принять решение о том, что оператор имеет 32 или 64 бит.

Это особенно важно во втором бите, где результат используется как индекс.