Ответ на вопрос практического интервью - PullRequest
14 голосов
/ 02 марта 2010

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

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

Вопрос "что не так с этим кодом?" И намекает, что это как-то связано с целевыми архитектурами.

Если ответ только "значение не инициализировано", я не вижу никаких проблем. Насколько я могу судить, он просто маскирует 2 младших байта значения, а long гарантированно будет по крайней мере 2 байта, так что проблем здесь нет.

Может ли быть так, что long может быть только 2 байта в целевой архитектуре, и вы можете потерять знаковый бит? Или, возможно, что 0xFFFF является int, а int - только 2 байта?

Заранее спасибо.

Ответы [ 6 ]

15 голосов
/ 02 марта 2010

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

Например, рассмотрим следующую программу:

#include <iostream>

int main(void)
{
    long value;
    value = -1; // Some stuff
    value &= 0xffff;
    std::cout << "Value = " << value << std::endl;
}

В архитектуре с двумя дополнениями результат:

Value = 65535

В архитектуре с одним дополнением результат:

Value = 65534

В архитектуре знака и величины результат:

Value = 1
7 голосов
/ 02 марта 2010

Трудно понять, что интервьюер ожидал от вас. Мы просто должны догадаться.

Я предполагаю, что на некоторых архитектурах 0xFFFF будет 16-битным значением со знаком, а long - 32-битным значением со знаком. Когда вы расширяете константу, чтобы ее можно было использовать для маскировки длинного значения, знак будет расширен и станет 0xFFFFFFFFl, что совсем не то, что вы намеревались.

Добавление: Написанный код правильно работает на всех трех компиляторах, которые я сейчас использую, так что это действительно игра в угадывание попыток выяснить, что имел в виду интервьюер. 16-битный компилятор, соответствующий стандартам, также будет генерировать правильный код, поэтому нам остается только догадываться, пропустили ли мы что-то, действительно ли пример не испорчен, или однажды интервьюер использовал 16-битный компилятор, который будет обрабатывать 0xFFFF как подписанное количество, когда вынуждено продлить его до длинных. Было бы интересно спросить его.

1 голос
/ 02 марта 2010

Могу я сказать, что в этом коде нет ничего плохого, если не известен контекст или намерение окружающего кода!

0 голосов
/ 02 марта 2010

Я подозреваю, что мы все слишком усердно думаем.

Что плохого в этом коде, это то, что значение не инициализировано. Вопрос в том, понимаете ли вы, что & = (или + =, - = / = и т. Д.) Не имеет смысла, когда используется для унифицированного значения?

Если значение инициализировано, то поведение хорошо определено. Младшие 16 бит сохраняются, остальные обнуляются

0 голосов
/ 02 марта 2010

Это может быть выстрел в темноте, но при условии, что long vs int не проблема (другие опубликовали ответы, отвечающие только на это) и что 0xFFFF охватывает всю сумму, требуемую типом, не будет это просто делает value = 0xFFFF и нет необходимости в битовых манипуляциях? Разве битовая манипуляция не избыточна?

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

Мне кажется, что вопрос задается довольно странно, в зависимости от того, как этот вопрос представлен здесь, или, может быть, это настолько очевидно, что мы все думаем об этом :)

0 голосов
/ 02 марта 2010

звучит как Big-Endian против Little-Endian для меня. http://en.wikipedia.org/wiki/Endianness

...