Поведение, определяемое реализацией в C

Пожалуйста, не могли бы вы сообщить какой-нибудь пример поведения, определенного реализацией в C?

Например, я знаю из стандарта, что "поведение, определяемое реализацией, - это распространение старшего бита, когда целое число со знаком сдвигается вправо".

Не могли бы вы объяснить мне значимость этого примера и привести пример?

Я это понимаю int i; i >> 3. Но почему это определяется реализацией?

3 ответа

Решение

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

Таких случаев в языке сотни. Стандарт содержит краткое изложение большинства из них в Приложении J.3, которое занимает около 15 страниц.

Конкретный пример int i; i >> 3 является неопределенным поведением, поскольку переменная не инициализирована.

Конкретный пример int i=0; i >> 3определяется реализацией, потому что так сказано в стандарте. C17 6.5.7/5:

Результат E1 >> E2 E1 сдвинут вправо E2битовые позиции. /--/ ЕслиE1 имеет знаковый тип и отрицательное значение, результирующее значение определяется реализацией.

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

Любой код, основанный на поведении, определяемом реализацией, гарантированно работает только на определенной платформе и / или компиляторе. Переносимые программы должны стараться избегать такого поведения.

Согласно: https://clc-wiki.net/wiki/C_language:Terms:Implementation-defined_behaviour

Это также дает еще один пример:

int *o = malloc(0 * sizeof *o);

может привести к o либо быть NULL или уникальный указатель (как указано в 7.20.3 стандарта C99).

Его реализация определена, потому что комитет по стандартам C отказался определять, что должно происходить. Причина, по которой они это сделали, заключается в том, что разные процессоры в таких обстоятельствах делают разные вещи, а идеал C (в интересах быстрого выполнения) состоит в том, чтобы не делать слишком много абстракции между исходным кодом C и кодами операций, выполняемыми на ПРОЦЕССОР.

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

Другие, несомненно, смогут указать на более авторитетные версии этого объяснения!

Другие вопросы по тегам