2011-04-14 6 views
5

Примечание: этот вопрос связан с подписью второго операндом операторов сдвига бит < < и >>. Совсем не о первом операнде.В C, например, почему второй операнд сдвига разрешен для подписания?

CERT INT34-C, в частности: Не переключайте отрицательное число битов ...

Не то, что ей необходимо оправдание, но они оправдывают говорят, что это undefined behavior.

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

Так что, если в C нет необходимости и не определено смещение на отрицательное количество бит, почему второй операнд < < или >> даже разрешено подписываться?

MISRA-C: 2004, например (что бы вы ни думали о MISRA, вроде или не нравится) в его разделе 6.10.2, как побочный эффект объяснения того, что тип результата зависит только от первого операнда, говорит что «второй операнд может быть любого подписан или беззнаковый целочисленный тип». [emphasis mine]

Зачем приглашать людей использовать подписанный второй операнд в сдвиге бит? Зачем это позволить? Предупреждают ли какие-либо компиляторы об этом?

+0

Допускается формально подписанный тип. Нельзя отрицать. Также не допускается превышать число бит в типе. Означает ли это, что C должно требовать использования битовых типов в 5 бит в качестве правого операнда для сдвигов по 32-битовому целому? Конечно, это было бы чушь. Если вам не нужен язык, который «приглашает» вас делать глупые вещи, вы, вероятно, должны начать искать другой язык. Но другие языки «приглашают» вас делать разные глупые вещи (например, конкатенация строк); вам будет сложно найти «идеальный» ... –

+0

@R истинно, что я не могу найти идеальный язык, но есть разница между двумя требованиями по второму операнду сдвига бит: неотрицательный требование может быть принудительно введено с помощью объявленного (и не литого) типа операнда, тогда как требование не слишком большого размера требует фактического изучения значения операнда. – talkaboutquality

ответ

4

Я не могу сказать, почему вещи, как они есть ... но я рад, что может сдвинуться подписанными значениями:

3 в выражении a <<= 3; является внутром.
Если вы перешли на int были незаконными, вам нужно будет сделать a <<= 3U;.

Сделать это незаконным для сдвига по подписанным значениям может сильно нарушить (я имею в виду A LOT) кода!

+0

Стоимость: возможно, менее читаемость в сложных выражениях сдвига (но их следует избегать для удобства чтения) Преимущества: гарантирует, что количество сдвигов не может быть отрицательным (предотвращает кодирование чего-либо, чье поведение не определено) Так почему это было бы плохо, если бы он был подписан количество сдвигов было запрещено? – talkaboutquality

+0

@talkaboutquality: Теперь рассмотрим 'int a; ... b << a; '. Если 'a' отрицательно, это проблема. Изменение его на '(unsigned) a' ничего не поможет, потому что' (unsigned) a' будет очень большим числом, а сдвиг влево на '(unsigned) a' приведет к неопределенному поведению в любом случае. –

+0

@ david-thornley, конечно, я не хотел позволять кастинге без знака, а просто изначально объявлял второй операнд как unsigned.Не уверен, что компиляторы могли бы предупредить и потребовать именно этого. Возможно, лучшей ссылкой будет https://www.securecoding.cert.org/confluence/display/seccode/INT13-C.+Use+bitwise+operators+only+on+unsigned+operands, в частности, с @pmg, его исключение «INT13-EX2: если операнд правой руки для оператора сдвига известен во время компиляции, допустимо, чтобы значение представлялось знаком типа, если оно положительно». – talkaboutquality

 Смежные вопросы

  • Нет связанных вопросов^_^