Зацикливание через байты длинной выдает байты дважды в 64-битных системах [duplicate]

db.student.find({}, {"roll":1, "_id":0})

Это эквивалентно -

Выбрать рулон из ученика

db.student.find ({}, {"roll": 1, «name»: 1, «_id»: 0})

Это эквивалентно -

Выбрать рулон, имя от ученика

8
задан Rakib 9 June 2014 в 11:15
поделиться

5 ответов

Хотя ваш x имеет тип long int, 1 нет. 1 является int, поэтому 1<<63 действительно не определено.

Попробуйте (static_cast<long int>(1) << 63) или 1L << 63, как предложено Wojtek.

7
ответ дан Luchian Grigore 24 August 2018 в 00:18
поделиться

Тип данных по умолчанию для числового значения в C является целым числом, если явно не указано.

Здесь вы должны ввести cast 1 как long int, который в противном случае был бы int.

1
ответ дан Arjun. M 24 August 2018 в 00:18
поделиться

Ваш заголовок вводит в заблуждение; a long может сдвигаться дальше 31 бит, если long действительно является большим. Однако ваш код сдвигает 1, который является int.

В C ++ тип выражения определяется самим выражением. Выражение XXXXX имеет тот же тип независимо; если вы позже перейдете double foo = XXXXX;, это не значит, что XXXXX является двойным - это означает, что преобразование происходит из того, что XXXXX было, double.

Если вы хотите сдвинуть влево длинный, то делайте это явно, например 1L << 32 или ((long)1) << 32. Обратите внимание, что размер long варьируется между платформами, поэтому, если вы не хотите, чтобы ваш код прерывался при запуске в другой системе, вам придется принимать дополнительные меры, например, использовать типы фиксированной ширины или перемещаться по CHAR_BIT * sizeof(long) - 1.

Существует еще одна проблема с вашим предполагаемым кодом: 1L << 63 вызывает неопределенное поведение, если long имеет значение 64 бит или меньше. Это связано с целым переполнением со знаком; левый сдвиг определяется так же, как повторное умножение на два, поэтому попытка «сдвигаться в бит знака» вызывает переполнение.

Чтобы исправить это, используйте неподписанные типы, где это нормально, чтобы перейти в MSB , например 1ul << 63.

Технически есть еще одна проблема в том, что ~0 не делает то, что вы хотите, если вы не используете систему дополнений 2, но в наши дни довольно безопасно игнорировать этот случай.

Глядя на ваше намерение с помощью long x = ~0 & ~(1 << 63). Более короткий способ написать это:

long x = LONG_MAX;

, который определен <climits>. Если вам нужна 64-разрядная версия на всех платформах, то

int64_t x = INT64_MAX;

NB. Если вы не собираетесь работать с отрицательными значениями, используйте unsigned long x и uint64_t соответственно.

2
ответ дан M.M 24 August 2018 в 00:18
поделиться

Вы не можете использовать 1 (int по умолчанию), чтобы переместить его за пределы int.

Существует более простой способ получить «все биты, кроме включенного MSB», для определенного типа данных

#include <iostream>
#include <limits>

using namespace std;

int main(){
    unsigned long int max = std::numeric_limits<unsigned long int>::max();
    unsigned long int max_without_MSB = max >> 1;
    cout<< max_without_MSB <<endl;
    return 0;
}

Обратите внимание на неподписанный тип. Без numeric_limits:

#include <iostream>
using namespace std;

int main() {

    long int max = -1;
    unsigned long int max_without_MSB = ((unsigned long int)max) >> 1;
    cout << max_without_MSB << endl;

    return 0;
}
3
ответ дан Marco A. 24 August 2018 в 00:18
поделиться

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

Нет гарантии, что long int на самом деле 64-битный.

Самый общий способ, которым я могу думать, - использовать std::numeric_limits:

static_cast<long int>(1) << (std::numeric_limits<long int>::digits - 1);

Теперь вы можете даже сделать эту шаблонную функцию constexpr:

template <typename Integer>
constexpr Integer foo()
{
    return static_cast<Integer>(1) << (std::numeric_limits<Integer>::digits - 1);
}

Таким образом, заменяя сдвиг с static_cast<long int>(1) << (std::numeric_limits<long int>::digits - 1) исправит вашу проблему, однако есть намного лучший способ:

std::numeric_limits включает в себя кучу полезных вещей, в том числе:

std::numeric_limits<T>::max(); // the maximum value T can hold
std::numeric_limits<T>::min(); // the minimum value T can hold
std::numeric_limits<T>::digits; // the number of binary digits
std::numeric_limits<T>::is_signed(); // well, do I have to explain? ;-)

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

2
ответ дан stefan 24 August 2018 в 00:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: