противоречие между c-faq и моим компилятором - PullRequest
0 голосов
/ 23 сентября 2010

C-faq говорит, что код:

int i = 7;
printf("%d\n", i++ * i++);

печатает 49. Независимо от порядка оценки, не должно ли печататься 56? Когда я запустил этот код на моем компиляторе Turbo C 3.0, он дал мне 56. Почему есть противоречие?

Ответы [ 4 ]

10 голосов
/ 23 сентября 2010

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

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

Таким образом, это может вывести 49 или 56. Неопределенное поведение, в конце концов, не определено.Вот почему нет реального противоречия.Возможно, вы захотите освежить свое понимание того, что называется точками последовательности.

4 голосов
/ 23 сентября 2010

Потому что неопределенное поведение . Компилятор может делать все, что захочет: он может печатать код 56, 49 или «твоя мама», и компилятор все равно будет соответствовать стандартам.

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

3 голосов
/ 23 сентября 2010

Выражение i++ * i++ вызывает неопределенное поведение, поэтому любой результат возможен.

Почему это не определено? Потому что языковой стандарт говорит так:

6.5 Expressions
...
2  Between the previous and next sequence point an object shall have its 
   stored value modified at most once by the evaluation of an expression.72) 
   Furthermore, the prior value shall be read only to determine the value 
   to be stored.73)
...
73) This paragraph renders undefined statement expressions such as

    i = ++i + 1;
    a[i++] = i;

while allowing

    i = i + 1;
    a[i] = i;

где "неопределенное поведение" означает

3.4.3
1 undefined behavior
  behavior, upon use of a nonportable or erroneous program construct or of 
  erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from <b>ignoring the situation 
  completely with unpredictable results</b>, to behaving during translation 
  or program execution in a documented manner characteristic of the environment 
  (with or without the issuance of a diagnostic message), to terminating a 
  translation or execution  (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

Акцент мой.

2 голосов
/ 23 сентября 2010

Действительно ли C-faq говорит это? Вы дважды модифицируете переменную (i) с помощью промежуточной точки последовательности, которая просто дает неопределенное поведение, ничего более или менее. Он может напечатать 49 или 56, или 73295, или вообще ничего, или «Форматирование жесткого диска ...» (и приступить именно к этому).

Редактировать: То, что может произойти, сводится к следующему: с постинкрементом часть приращения может происходить где угодно между моментом получения значения и следующей точкой последовательности. Сгенерированный код может легко действовать так:

int temp = i;
++i;
int temp2 = i;
++i;

printf("%d\n", temp * temp2);

С другой стороны, он также может действовать так:

int temp = i;
int temp2 = i;
++i;
++i;
printf("%d\n", temp * temp2);

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

...