На C / C ++, какие вещи в основном зависят от компилятора? - PullRequest
1 голос
/ 11 октября 2011

Какие задачи, функции, исполнения зависят от компилятора?Я знаю, что этот код зависит от компилятора -

#include <stdio.h>
#define PRODUCT(x)(x*x)
int main()
{
int i=3,j,k;
j=PRODUCT(i++);
k=PRODUCT(++i);
printf("\n%d %d",j,k);
}

Следующее дает мусор в некоторых, а фиксированные значения в других -

#include <stdio.h>
int main()
{
int i=5,j=10;
printf("%d,%d");
}

Так что порядок выполнения зависит от компилятора.Можно ли задавать такие неоднозначные программы на экзаменах?

Ответы [ 8 ]

12 голосов
/ 11 октября 2011

Если вы хотите получить полный список, вам нужно обратиться к стандартному документу. В стандарте C есть два типа «зависимых от компилятора» проблем определено:

  • Поведение, определяемое реализацией: поведение может варьироваться от компилятора к компилятору, но компилятор должен обеспечивать своего рода согласованное поведение и документировать это поведение. Пример, прямо из стандарта: «Примером поведения, определенного реализацией, является распространение старшего бита, когда целое число со знаком сдвигается вправо». Другими словами, результат -1 >> 1 может варьироваться в зависимости от компилятора, но компилятор должен быть последовательным по этому поводу.
  • Неопределенное поведение: все ставки выключены. В тот момент, когда вы нажмете неопределенное поведение, что угодно - и я имею в виду все, что может произойти. Ваш код является хорошим примером этого - вы изменяете одну переменную дважды без промежуточной точки последовательности (в нарушение ограничения §6.5 ISO / IEC 9899: 1999 (E)). А во втором у вас отсутствуют параметры (неопределенное поведение согласно §7.19.6.1 / 2). Согласно строгому прочтению стандарта, в этом случае компилятору вполне оправдано вызывать демонов через нос.

Вам также необходимо следить за нарушениями ограничений. Часто стандарт определяет такие вещи, как «[main] должен быть определен с типом возврата int [...]» (§5.1.2.2.1 / 1). Это эквивалентно: «Если объявлено main с типом возврата , отличным от int, поведение программы не определено». (см. п. 4.2, где стандарт явно подтверждает эту интерпретацию)

Вам не следует задавать эти вопросы на экзамене; если да, вы должны просто заявить, что поведение программы не определено (или определено реализацией). Обратите внимание, что некоторые определяемые реализацией поведения имеют ограничения - например, значение sizeof(int) определяется реализацией, но вы знаете, что sizeof(int) >= sizeof(short) && sizeof(int) <= sizeof(long) - так что наличие любого определяемого реализацией поведения не означает, что вы можете не говорите ничего о том, что делает программа.

3 голосов
/ 11 октября 2011

Как вы уже спрашивали о C ++, вот ответ C ++ 11 (который отличается от C ++ 98 и C99):

  • условно поддерживаемые конструкции (1.3.5)
  • поведение, определяемое реализацией (1.3.10), очевидно,
  • пределы реализации (1.3.11), такие как максимальное количество аргументов функции.
  • доступные локали иих поведение (1.3.12, 1.4)
  • неопределенное поведение (1.3.25)
  • выданные диагностические сообщения (1.4), не все ошибки требуют диагностики.
  • подробности реализациистандартной библиотеки (1.4) - охватывает множество возможных вариантов.
  • расширения (1.4)
  • используемые наборы символов (2.3)

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

3 голосов
/ 11 октября 2011

Можно ли задавать такие неоднозначные программы на экзаменах?

Естественно, это зависит от лица, проводящего экзамен, и темы экзамена.Я не был бы удивлен, увидев программу, содержащую неопределенное поведение на экзамене по языку программирования C, но я был бы очень удивлен, если бы «правильный» ответ был чем-то иным, чем «поведение этой программы не определено».

3 голосов
/ 11 октября 2011

Это не двусмысленность компилятора - ваша программа некорректна.

Двойное увеличение одной и той же переменной в выражении приводит к неопределенному поведению.

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

Чтобы ответить на ваши вопросы, основные компиляторы (GCC, MSVC) не отличаются какими-либо действительно существенными способами, которые я знаю оПо крайней мере, пока вы не попадете в стратосферу метапрограммирования.Похоже, что они оба оптимизируются примерно одинаково и имеют одинаковую поддержку функций C ++ 11.

3 голосов
/ 11 октября 2011

Первый фактически зависит от компилятора, потому что он разрешается в (i++ * i++).Компилятор может упорядочить эти операции для собственных нужд, потому что выражение не имеет «точек последовательности».

В Википедии есть хорошая статья о точках последовательности .

* 1007.* Первый пример - это действительно то, что происходит в викторинах, и правильный ответ - «результат неопределенный».

Второй - просто неверный;вам повезло, что это не дало вам ошибку сегментации или тому подобное.Обратите внимание на printf: он пытается извлечь два значения из стека, которые не были переданы.Значение, которое вы видите напечатанным, - это то, что происходит в стеке, и если после вас будет вызван другой вызов функции, в этот момент он, скорее всего, потерпит неудачу.

0 голосов
/ 11 октября 2011

Я рекомендую вам получить копии стандартов C и C ++ (их недорого купить или вы можете использовать один из общедоступных черновиков) и прочитать их.

При чтении обратите внимание на всевещи, которые помечены как unspecified behavior, undefined behavior, implementation-defined behavior, common extensions и т. д.

В стандарте C этот раздел, Приложение J "Проблемы с переносимостью", полностью посвящен этой теме.вид вещей.Подобные вещи (включая различия между C и C ++) также перечислены в стандарте C ++.

Стандарты дадут вам окончательные ответы на вопросы этого типа.Также обратите внимание на несовместимое (со стандартным) поведение вашего компилятора, также проверьте его документацию.

0 голосов
/ 11 октября 2011

Ну, слишком много, я думаю, что один из способов найти их - проверить C99 стандарт , а затем найти ключевое слово undefined и implementation-defined.

0 голосов
/ 11 октября 2011

Обе программы вызывают неопределенное поведение (UB).

  • Первая программа вызывает UB, потому что макрос расширяется до i++ * i++ и ++i*++i соответственно, и каждое выражение вызывает UB,так как они оба пытаются изменить объект i более одного раза без какой-либо промежуточной точки.

  • Вторая программа вызывает UB, поскольку строка format несопоставьте аргументы.

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