почему компилятору решать, какое значение присваивать при назначении значения вне диапазона переменной - PullRequest
1 голос
/ 05 июня 2010

в C ++ Primer 4th edition 2.1.1 говорится, что «при назначении значения вне диапазона для типа со знаком, компилятору решать, какое значение присвоить».

Я не могу этого понять. Я имею в виду, что если у вас есть код, такой как "char 5 = 299", компилятор сгенерирует код asm, такой как "mov BYTE PTR _sc$[ebp], 43" (VC) или "movb $43, -2(%ebp)" (gcc + mingw), это решается компилятором.

а что если мы присвоим значение, которое задается пользовательским вводом? как через командную строку? и сгенерированный код asm будет "movb %al, -1(%ebp)" (gcc + mingw) и "

mov cl, BYTE PTR _i$[ebp]
mov BYTE PTR _sc$[ebp], cl

"(VC), так что теперь, как компилятор может решить, что произойдет? Я думаю, что теперь это решается процессором.

Можете ли вы дать мне четкое объяснение?

Ответы [ 7 ]

12 голосов
/ 05 июня 2010

Компилятор должен решать, разрешать ли ему процессор. :)

Стандарт C ++ определяет, как должна вести себя ваша программа. Компилятор гарантирует, что такое поведение достигается. если вы делаете что-то, что не указано в стандарте, то компилятор может делать все что угодно. Он может выдать сообщение об ошибке, отправить электронное письмо вашей бабушке или взломать ваш банковский счет. Или он может генерировать код в любом случае, и да, тогда все зависит от процессора, что будет дальше.

Но дело в том, что процессор не отвечает за то, чтобы ваша программа вела себя так, как указано в стандарте C ++. Компилятор есть. Итак, компилятор должен обрабатывать любое отклонение от стандарта (даже если он часто решит ничего не делать особенного, это все равно решение компилятора)

3 голосов
/ 05 июня 2010

Это будет пример неопределенного поведения . Стандарт C ++ содержит много предложений, подобных этому: «Если (некоторое условие), результатом будет неопределенное поведение».

Почему существует неопределенное поведение? Разве это не усложняет ситуацию? Да, к сожалению, это все усложняет для программиста . Причина для UB состоит в том, чтобы упростить задачу для авторов компиляторов - либо упростить (или вообще возможно!) Написать компилятор в первую очередь, либо упростить компилятору оптимизацию, сделав определенные предположения.

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

Но существуют также нарушения, которые трудно или невозможно обнаружить компилятору. Примером этого может быть кусок памяти, который вы продолжаете использовать после того, как вы вызвали delete для него. На самом деле теоретически невозможно написать программу, которая обнаружит все возможные подобные нарушения. Поэтому вместо того, чтобы просить авторов компилятора решить неразрешимую проблему обнаружения этих нарушений, стандарт C ++ просто объявляет, что ваша программа будет испытывать «неопределенное поведение», если вы это сделаете. Это означает, что вы не можете делать любое предсказание того, что произойдет - фактически стандартный пример состоит в том, что UB может заставить демонов вылететь из вашего носа .

[EDIT] На самом деле, как указывает litb, ваш конкретный случай - не пример неопределенного поведения, а поведения, определяемого реализацией , что немного более цивилизованно. :) В этой категории описываются случаи, когда авторы стандарта C ++ признают, что программист может разумно ожидать какого-то согласованного поведения, что не слишком сложно для разработчика компилятора, но требовать такого поведения было бы обременительным или контрпродуктивным. быть одинаковым на каждой реализации. (Например, sizeof (int) определяется реализацией - хотя это часто 4 или 8, что касается стандарта C ++, единственное требование - >= sizeof (short).) Чтобы компилятор требовал соответствия стандарту, он должен задокументируйте конкретное поведение, которое будет иметь место для каждого сценария, помеченного как «определяемое реализацией поведение» в стандарте.

3 голосов
/ 05 июня 2010

конечно. «Вплоть до компилятора» в данном случае (книга Стэнли Липпмана) означает «это не предписывается стандартом».

Компилятор специально не решает или не обязательно генерирует код для обработки этого случая. Это может зависеть от платформы.

2 голосов
/ 05 июня 2010

Я думаю, что это относится к такой ситуации:

char c = 3456234242424 ;

3456234242424 больше, чем может содержать подписанный символ, поэтому он будет переполнен. Затем следует установить максимальное положительное значение для символа или минимальное отрицательное значение? Это не обязательно в языковом стандарте, поэтому решать, какое значение присвоить .

, должен компилятор

Другое общее описание этого «зависит от реализации». Сам язык не обязывает что делать, но что-то должно быть сделано. Таким образом, компилятор, который реализует язык, может / должен решить.

2 голосов
/ 05 июня 2010

конечно, компилятор будет генерировать asm-код, такой как

Вы путаете язык C ++ с одной возможной реализацией на одной конкретной платформе.

1 голос
/ 05 июня 2010

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

0 голосов
/ 05 июня 2010

Процессоры «никогда» не выходят из строя, и им нечего решать, поскольку невозможно, чтобы они обрабатывали значение вне допустимого диапазона. В фрагментах asm вообще нет информации о значении вне допустимого диапазона, и не может быть иначе, если инструкция сгенерирована правильно (а ассемблеры вообще не будут собираться, если операнд не соответствует размеру операция, например, mov al, 123456ABh вызывает ошибку, и код не генерируется, поскольку нет инструкции, которая, конечно, позволяет загрузить 8-битный регистр с 32-битным значением!).

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

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