2013-07-04 4 views
6

В этом C-FAQ дается около sequence point;Точки последовательности и побочные эффекты в C

В стандарте указано, что;
Между предыдущей и следующей точками последовательности объект должен иметь значение хранимого значения, измененное не более одного раза путем оценки выражения. Кроме того, к предыдущему значению следует обращаться только для определения значения, которое необходимо сохранить.

В примерах

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

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

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

i = i + 1 

допускается, поскольку доступ I используется для определения I, конечное значение. Пример

a[i] = i++ 

запрещен, потому что один из доступов I (один в [I]) не имеет ничего общего со значением, которое заканчивает тем, что хранится в I (который бывает в i ++), и поэтому нет хорошего способа определить.

Мои вопросы:
1. Что это значит, , если объект написан в полном выражении, любые и все обращения к нему в пределах одного и того же выражения должны непосредственно участвовать в вычислении значения, которое должно быть записано.?

2.Что делает это означает, по, пример a[i] = i++ запрещенный потому, что один из доступов I (один в [I]) не имеет ничего общего со значением, которое заканчивает тем, что хранится в I (что происходит в i ++)
Может ли кто-нибудь объяснить это каким-то простым способом?

ответ

1

Наконец-то я получил explanation по этому поводу. После прочтения его и FAQя заключил что;

1. Последнее предложение

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

бы, как это;

Кроме того, предшествующее значение объекта должно быть доступно только для определения модифицированного/нового значения (тех же объекта) должны быть сохранены.

Как видно на примере

int i = 1, j, a[5];  
i = i + 1; 
j = i + 1; 
a[i] = i; 

в случае выражения i = i + 1 предшествующее значение (которое 1 здесь) из i (в RHS) осуществляется доступ, чтобы определить значение i быть хранится, и это то, что заявление

Если объект записан в полном выражении, все и все его обращения к нему в пределах одного выражения mu st непосредственно участвуют в вычислении значения, которое должно быть записано .

говорит.
Хотя в случае j = i + 1 и a[i] = i, к которому осуществляется доступ значение i является только дорожитнеперед значения, как ни где i модифицируются в этих заявлениях.

2. Второй вопрос можно объяснить следующим образом:
В случае экспрессии a[i] = i++ или a[i++] = i, первое предложение выше заявление

Между предыдущей и следующей точкой последовательности объект должен быть его сохраненное значение модифицированного не более одного раза в ходе оценки выражения.

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

+0

эй @haccks согласно вашему второму объяснению, вы предположили, что значение, которое мы пишем, это «i», но на самом деле это [i] .... путаница для меня. Пожалуйста, покажите мне путь! – YakRangi

+0

@Bayant_singh; В какой строке? – haccks

+0

Между предыдущей и следующей точками последовательности объект должен иметь измененное значение хранимого значения не более одного раза путем оценки выражения. – YakRangi

3

Это объяснение странно, и я не могу понять это.

Настоящим объяснением является то, что выражение i++ имеет побочный эффект (приращение i), который может быть применен в любое время после того, как этот конкретный i был оценен.

Поскольку вне последовательности точек, язык C не гарантирует порядок оценки или время, когда пост-incrementations применяется (вероятно, по соображениям производительности), три вещи, которые могут произойти во втором примере (предположим i = 5 перед строкой):

  • Крайний левый i (один в a[i]) сначала вычисляется, для вычисления адреса [I] для хранения. Затем правый i оценивается, то пост-инкрементации наносится: линия выполняет a[5] = 5; i=6;
  • Крайний правый i сначала вычисляется, затем крайний левый один, а затем i пост-инкрементации применяется, когда все сказано и сделано : В этом случае эффекты идентичны описанному выше случаю.
  • Сначала оценивается крайняя правая сторона i, а затем крайняя поправка i оценивается для вычисления адреса [i] для хранения. На этот раз эффект составляет a[6] = 5; i=6.

Выбор результата зависит не только от выбора компилятора, но и от параметра компилятора: Microsoft Visual C++ может давать разные результаты в зависимости от того, компилируете ли вы в Debug или Release.

+0

Ваши объяснения касательно UB 'a [i] = i ++', и вы объяснили это хорошо, но мне нужно объяснение для моих вопросов. – haccks

+0

Увы, я не вижу объяснения частей, которые вы цитировали. Мне они кажутся бессмысленными. – Medinoc

+0

Да, это также бессмысленно для меня, и именно поэтому я задал этот вопрос. – haccks

6

Мой вопрос: 1. Что это значит, если объект записывается в пределах полного выражения, любой доступ к нему в пределах одного выражения должен быть непосредственно вовлечен в вычисление значения, которое должно быть записано.?

С таким выражением, как i++, i. Кроме того, присваивание является выражением, поэтому в i = 2, i написано. Не может быть сразу очевидно, что выражение a = b - это выражение. Вот почему вы можете делать такие вещи, как a = b = c, что хорошо, и if (a = b), что не так хорошо.

Так что, если вы пишете i, с = или до или после инкремента, то любой доступ к i должен быть как часть вычисления нового значения i. Однако, и это важно, единственное, что связано с вычислением до и после приращения, - это значение iв начале отчета.

2.Что делает это в виду,, Пример A [I] = я ++ запрещена, потому что один из доступов из I (один в [I]) не имеет ничего общего со значением, которое заканчивается вверх хранится в i (что происходит в i ++)

Именно то, что он говорит. Когда вы получаете доступ к i в a[i], он не является частью расчета нового значения i, что соответствует i++.

Может кто-нибудь объяснить это каким-либо простым способом?

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