Что не так с этим кодом битовой манипуляции из интервью? - PullRequest
25 голосов
/ 23 ноября 2010

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

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

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

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

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

Спасибо!

Ответы [ 7 ]

41 голосов
/ 23 ноября 2010

Несколько ответов здесь утверждают, что если 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 не инициализируется при объявлении, но это, вероятно, комментарий уровня нит-пика и зависит от содержимого пропущенного раздела //some stuff.

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

3 голосов
/ 23 ноября 2010

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

2 голосов
/ 23 ноября 2010

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

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

1 голос
/ 23 ноября 2010

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

0 голосов
/ 13 июня 2014

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

0 голосов
/ 23 ноября 2010

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

0 голосов
/ 23 ноября 2010
* Размер шрифта

зависит от платформы / компилятора.

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

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