множественный ++, работающий с переменными и указателями

Это то, что я думаю++ оператор делает

a++; // a+=1 after calculating this line++a; // a+=1 before calcuating this line

Я пытаюсь изучить указатели, и я думаю, что я что-то неправильно понял.

int a=10;
int arr[3]={0,1,2};
int *ptr;
ptr=arr;

printf("%d,%d,%d,%d\n",a++,a++,++a,++a);
printf("%d,%d,%d\n", ptr[0],ptr[1],ptr[2]);
printf("%d,%d,%d,%d,%d,%d", * ptr++, ( * ptr)++, ++ * ptr, ++( * ptr), *++ptr, * ptr);

Я ожидал, что на выходе будет:

12, 12, 12, 12
0,1,2
3,3,3,3,3,3,3

Но это не былот. Это было так:

13,12,14,14
0,1,2
4,3,2,2,2,2

Почему это?

 Rhee12 нояб. 2009 г., 06:38
@Chris Lutz-2 минуты назад, лол
 Thorsten12 нояб. 2009 г., 06:29
И что'Ваш вопрос?
 Rhee12 нояб. 2009 г., 06:33
Сэр Крис Латс отредактировал сообщение для меня: D извините за мой плохой английский!
 Chris Lutz12 нояб. 2009 г., 06:33
@ Ри - сэр? Когда я был посвящен в рыцари?

Ответы на вопрос(4)

Решение Вопроса

Вы'не следует делать более одного приращения аргументов функции .. потому что порядок, в котором они могут быть оценены, неоднозначен. Результат такого кода не определен.

Имея в виду:printf("%d,%d,%d,%d\n",a++,a++,++a,++a); Должно быть написано как

a++; a++;
++a; ++a;
printf("%d, %d, %d, %d\n", a, a, a, a);

Попробуйте сначала исправить это и посмотрите, не сбивают ли результаты с толку.

В целом, вы должны иметь только один шаг между паройпоследовательность точек.

Редактировать: Крис прав, тамНет смысла писать четыре шага в середине нигде. Чтобы лучше ответить на ваш вопрос: для функцииvoid f(int) а такжеvoid g(int), с ,int a=0

f(++a) = f(1);
f(a++) = f(0);
g(++a, ++a) = g(???); // undefined!

Таким образом, приращение не более одного раза в аргумент функции.

 Chris Lutz12 нояб. 2009 г., 06:41
@Murali - Этоs, вероятно, не определено, потому что GCC выпустил более 9000 предупреждений, говорящих "это, вероятно, неопределенное поведение когда я пытался скомпилировать это.
 Heath Hunnicutt12 нояб. 2009 г., 06:40
Мурали, на самом деле монтажник верен - порядок вычисления не определен в компиляторах Си. Вы можете использовать компилятор, который делает то, что вы описываете. Это'Поведение также может измениться, если вы включите оптимизацию.
 int312 нояб. 2009 г., 06:42
Мурали: возможно, именно так его реализует компилятор, но стандарт говорит, что выя не должен этого делать.
 Murali VP12 нояб. 2009 г., 06:42
Да, у меня сложилось неверное впечатление, я забираю свой комментарий.
 Rhee12 нояб. 2009 г., 06:36
Хорошо, попробую, спасибо!
 Chris Lutz12 нояб. 2009 г., 06:38
Технически этодолжен быть написано какa += 4, но тогда зачем нам печатать его 4 раза? Этот код исследует неопределенное поведение, и попытка не вызывать неопределенное поведение делает его бесполезным. Это'Лучше сказать, что код вызывает неопределенное поведение и оставить все как есть.
 Murali VP12 нояб. 2009 г., 06:38
здесь нет "должен ", нет никакой двусмысленности, и это не неопределенно. Это вопрос оценки слева направо и выталкивания в стек справа налево.

Это'неза строку ", его "за точку последовательности который похож на "за выражение " что результат до и после увеличения, похоже, имеет место.

На самом деле, приращение всегда происходит немедленно. Единственное изменение заключается в том, приведет ли значение термина к первоначальному или последующему значению.

Чтобы полностью понять, что C не является линейно-ориентированным, пожалуйста, обратитесь к стандарту и прочитайте части о "последовательность точек. "

Строки, начинающиеся с '#' являются входом препроцессора. Препроцессор для C ориентирован на строки, но, в противном случае, сам C считает символы переноса строки такими же, как любые другие пробелы, такие как табуляция или пробел.

 Heath Hunnicutt12 нояб. 2009 г., 06:41
Поскольку splicer переписал ваш код - он разделил приращения точками с запятой, которые обозначают операторы в C.
 Rhee12 нояб. 2009 г., 06:37
так как я могу отделить выражение в этом коде?

Дон»сделать это Поведение не определено.

Из спецификации C (раздел 6.5) ...

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

За исключением случаев, обозначенных синтаксисом или иным образом указанным позже (для оператора вызова функции (), && , || ,?: и операторы запятой), порядок вычисления подвыражений и порядок возникновения побочных эффектов не определены.

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

 Rhee12 нояб. 2009 г., 06:42
хорошо, что 'ясно, спасибо!

Смотрите 3.2 в C FAQ:

3.2: под моим компилятором код

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

отпечатки 49. Независимо от порядка оценки, не долженТ это печатать 56?

A: Хотя операторы postincrement и postdecrement ++ и - выполняют свои операции после получения первого значения, подразумевается "после" часто неправильно понимают. этоне Гарантируется, что увеличение или уменьшение выполняется сразу же после отказа от предыдущего значения и до оценки любой другой части выражения. Просто гарантируется, что обновление будет выполнено за некоторое время до того, как будет рассмотрено выражение.законченный" (до следующего "точка последовательности " в ANSI C 'терминология; см. вопрос 3.8). В этом примере компилятор решил умножить предыдущее значение самостоятельно и выполнить оба приращения позже.

Поведение кода, содержащего множество неоднозначных побочных эффектов, всегда было неопределенным. (Грубо говоря,множественные, неоднозначные побочные эффекты » мы имеем в виду любую комбинацию операторов приращения, убывания и присваивания в одном выражении, в результате чего один и тот же объект либо модифицируется дважды, либо модифицируется, а затем проверяется. Это грубое определение; см. вопрос 3.8 для точного ответа и вопрос 11.33 для значения "не определены «.) Дондаже попытаться выяснить, как ваш компилятор реализует такие вещи (вопреки опрометчивым упражнениям во многих учебниках по Си); просить&R мудро указать, "если ты нене знаюкак они сделаны на разных машинах, чтобы невинность могла защитить вас ".

Рекомендации: K &R1 Sec. 2,12 стр. 50; K &R2 Sec. 2,12 стр. 54; ISO Sec. 6.3; ЧАС&S Sec. 7,12 с. 227-9; CT &P Sec. 3.7 стр. 47; PCS Sec. 9,5 с. 120-1.

 Chris Lutz12 нояб. 2009 г., 06:50
Aaaah! Большие страшные блоки текста!
 Rhee12 нояб. 2009 г., 06:52
правда, сейчас читаю эти тексты для моих английских способностей. верю что-то будет лучше
 Sinan Ünür12 нояб. 2009 г., 07:02
Кажется, c-faq.com не работает, и faqs.org не позволяет мне ссылаться на отдельные вопросы.

Ваш ответ на вопрос