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

Что не так с этим кодом бит-манипуляции из вопроса интервью?

Я просматривал эту страницу: http://www.devbistro.com/tech-interview-questions/Cplusplus.jsp и не понял этого вопроса:

Что может быть неправильным в следующем коде?

long value;
//some stuff
value &= 0xFFFF;

Примечание: подскажите кандидату о базовой платформе, для которой они развиваются. Если человек все еще не находит ничего плохого в коде, они не имеют опыта работы с С++.

Может ли кто-нибудь уточнить это?

Спасибо!

4b9b3361

Ответ 1

В нескольких ответах говорится, что если int имеет ширину 16 бит, 0xFFFF отрицательный. Это неправда. 0xFFFF никогда не является отрицательным.

Шестнадцатеричный литерал представлен первым из следующих типов, который достаточно велик, чтобы содержать его: int, unsigned int, long и unsigned long.

Если int имеет ширину 16 бит, то 0xFFFF больше максимального значения, представляемого int. Таким образом, 0xFFFF имеет тип unsigned int, который гарантированно будет достаточно большим, чтобы представлять 0xFFFF.

Когда для оценки & выполняются обычные арифметические преобразования, unsigned int преобразуется в long. Преобразование 16-битного unsigned int в long корректно определено, потому что каждое значение, представляемое 16-разрядным unsigned int, также представляется 32-разрядным long.

Нет необходимости в расширении знака, потому что начальный тип не подписан, а результат использования 0xFFFF совпадает с результатом использования 0xFFFFL.

В качестве альтернативы, если int шире 16 бит, то 0xFFFF имеет тип int. Это подписанное, но положительное число. В этом случае оба операнда подписаны, а long имеет больший ранг преобразования, поэтому int снова повышается до long с помощью обычных арифметических преобразований.


Как говорили другие, вам следует избегать выполнения побитовых операций над подписанными операндами, потому что числовой результат зависит от того, как отображается подпись.

Помимо этого, в этом коде нет ничего особенного. Я бы сказал, что это относится к стилю, что value не инициализируется, когда он объявлен, но, вероятно, комментарий уровня nit-pick и зависит от содержимого раздела //some stuff, которое было опущено.

Возможно, предпочтительнее использовать целочисленный тип фиксированной ширины (например, uint32_t) вместо long для большей переносимости, но на самом деле это тоже зависит от кода, который вы пишете, и от каких основных допущений.

Ответ 2

Я думаю, что в зависимости от размера long литерал 0xffff (-1) можно было бы продвигать до большего размера и быть подписанным значением, он будет расширен знаком, потенциально становясь 0xffffffff (все еще -1).

Ответ 3

Я предполагаю это, потому что предопределенного размера для long нет, кроме того, он должен быть как минимум размером с предыдущий размер (int). Таким образом, в зависимости от размера вы можете либо обрезать значение подмножеству битов (если оно длиннее 32 бита), либо переполнение (если оно меньше 32 бит).Забастовкa >

Да, longs (по спецификации и спасибо за напоминание в комментариях) должны иметь возможность удерживать не менее -2147483647 до 2147483647 (LONG_MIN и LONG_MAX).

Ответ 4

Для одного значения не инициализируется, прежде чем делать это, и поэтому я думаю, что поведение undefined, значение может быть любым.

Ответ 5

размер длинного типа - специфичный для платформы/компилятора.

Что вы можете здесь сказать:

  • Он подписан.
  • Мы не можем знать результат значения & = 0xFFFF; поскольку это может быть, например, значение & = 0x0000FFFF; и не будет делать то, что ожидалось.

Ответ 6

Хотя можно утверждать, что, поскольку это не переполнение буфера или некоторая другая ошибка, которая может быть использована, это вещь стиля, а не ошибка, я на 99% уверен, что ответ, который ищет автор вопроса поскольку это означает, что value работает до того, как он назначен. Значение будет произвольным мусором, и вряд ли это будет означать, так что это "потенциально неправильно".

Ответ 7

Используя MSVC, я думаю, что оператор будет выполнять то, что, скорее всего, предназначено, то есть: очистить все, кроме наименее значимых 16 бит значения, но я столкнулся с другими платформами, которые интерпретировали бы литерал 0xffff как эквивалент (короткий) -1, затем знак растягивается, чтобы преобразовать в long, и в этом случае выражение "значение & = 0xFFFF" не будет иметь эффекта. "value & = 0x0FFFF" является более явным и надежным.