Задачка про С

bleyman

int i = 0;
int *n = &i;
i++[n]--[n]++;
1. Скомпиляется ли это.
2. Если нет то почему
3. Если да то
а. чему равно i
б. вообще всё ли здесь в порядке
(http://www.livejournal.com/users/vorber/6484.html)

disna

1. да
3.
а. 1
б. а хз

bleyman

Ебанись!
У меня i == 2 =)
Либо глючит мс компайлер, либо я ничего не понимаю

laki

я скомпилил под gcc тоже 1у получил

Bird_V

1. Da, skompliltsya
2. -
3a. 0
3b. Net, ne vse: ispol'zovanie neallokirovannoj pamyati. Normal'naya sistema za eto poshlet.

maggi14

А почему 0? Имхо 1.
Нет, не любая система пошлет, как мне кажется. В досе бы нормально сработало.

tony33

Ну раз выражение
i++[n]--[n]++;
эквивалентно
n[n[i++]--]++;
значит содержимое переменной i два раза увеличили и один раз уменьшили.
i = 1

bleyman

Чуваки, это жёпа.
1) Мои рассуждения (вроде правильные):
Смотрим прецеденс оф операторс. У постфиксного ++, -- и [] одинаковый приоритет и лефт ту райт ассоциативность. Получаем
i++)[n])--)[n])++;
ну и начинаем по частям преобразовывать и интерпретировать
"i++)[n])--)" == "(n[i++])--)" == "{ temp=i /* 0 */; i++; temp2 = n[temp]; n[temp]--; return temp2;", то есть в i получаем опять 0, но значение выражения 1 (и это лвалью, так что можно смело подставлять дальше единичку).
Далее видим
"(1[n])++;" == "n[1]++". n мы не двигали, то есть фактически мы увеличиваем что-то левое на 1.
Ответ: Скомпиляется, i = 0, в качестве побочного эффекта мы увеличили что-то на 1, поэтому не всё в порядке.
2) Изучаем поведение микрософт вижуал С/С++ компайлера!
a = i++[n]--[n]++;
ответ: i = 2
------
i++)[n])--)[n])++;
ответ: i = 2 (то есть скобочки я правильно расставил)
------
a = i++)[n])--;
printf("a = %d, b = %d, c = %d, i = %d\n", a, b, c, i);
b = (a[n])++;
printf("a = %d, b = %d, c = %d, i = %d\n", a, b, c, i);
Ответ:
a = 0, b = 0, c = 0, i = 0
a = 0, b = 0, c = 0, i = 1
(то есть i = 1)
------
a = i++;
printf("a = %d, b = %d, c = %d, i = %d\n", a, b, c, i);
b = (a[n])--;
printf("a = %d, b = %d, c = %d, i = %d\n", a, b, c, i);
c = (b[n])++;
Ответ:
a = 0, b = 0, c = 0, i = 1
a = 0, b = 1, c = 0, i = 0
a = 0, b = 1, c = 1310424, i = 0
То есть так оно и должно работать. Значение c, правда, не очень понятное получилось. Жёппа какая-то. Все ищем компилятор С соответствующий стандарту! =) Ну или ошибку у меня.

bleyman

>> n[n[i++]--]++;
n[i++]-- должно быть равно единице.

Marinavo_0507

Побочный эффект от операций ++ и -- по стандарту имеет право наступать в любое время, но я не помню точную формулировку того, какое время считается любым, сами смотрите.

tony33

с какого перепоя? Ты хочешь сказать он залезет в чужую память?
Все ++ и -- происходят после того как результат всей хрени будет известен

bleyman

> Все ++ и -- происходят после того как результат всей хрени будет известен
С какого перепоя?
Так вот, ответ 2, между прочим %) Объясни это!

tony33

Вот что происходит в gcc
printf ("i = %d\n", n[i++]--);
printf ("i = %d\n", i);
на экране
i = 0
i = 0

tony33

Проверь что у тебя выводит

bleyman

Ужос кокой!
EXAMPLE 7 The grouping of an expression does not completely determine its evaluation. In the following fragment
#include <stdio.h>
int sum;
char *p;
/* ... */
sum = sum * 10 - '0' + (*p++ = getchar;
the expression statement is grouped as if it were written as
sum = sum * 10) - '0') + *(p++ = (getchar;
but the actual increment of p can occur at any time between
the previous sequence point and the next sequence point (the
, and the call to getchar can occur at any point prior to
the need of its returned value.
То есть a[i++] = i; тоже даёт undefined result. Отлично!

tony33

>С какого перепоя?
Опыт работы с компилятором gcc, а по стандарту хз

sergey_m

По-моему память аллоцируется постранично, поэтому небольшой выход за границы переменных не будет караться SIGSEGV. Кстати в этой памяти может быть всё что угодно, и этим можно объяснить тот факт, что результат получается разный на разных машинах.
P.S. /me пьян, поэтому не судите строго, коли сказал хуйню.

Svyatogor

Объясняю, почему ответ все-таки бывает 2.
MSVC считает, что все постэффекты независимы друг от друга. Тогда получаем следующее:
n[n[i++]--]++ эквивалентно n[n[i]--]++; i++, что в свою очередь эквивалентно n[n[i]]++; n[i]--; i++. Ну а это, как легко убедиться, и дает значение i = 2.
Для проверки надо выполнить примерно следующее:

int i, j;
int *n = &i;
j = 667;
n[n[i++]--]++;
printf("%d %d\n", i, j);

Я это не проверял, но предполагаю, что результат будет "2 666".
P.S. В стандарте не сказано, что выражение не может вычисляться несколько раз. Но при этом все вызовы функций вызываются не больше раз, чем их написано в выражении, т.к. функции могут иметь побочные эффекты.

rosali

Ну зачем такой сложный пример, напиши
 x=x++; 
и фтыкай. Какое вообще приоритет операторов имеет отношение к порядку вычисления? Приоритет определяет как будет _выглядеть_ дерево выражения, а не как оно будет _вычисляться_. Написал, например,
f + g + h 

Сложение левоассоциативно, то есть скобки подразумеваются такие:
(f + g + h 

но это всего лишь означает, что то, что вернет f будет прибавлено к тому, что вернет g, и не имеет никакого отношения к тому, что отработает раньше, f или g или вообще h.
Вот такой вот трудный язык, вот так вот сложно писать выражения с побочным эффектом.

Flack_bfsp

При ленивых вычислениях (например, оператор &&) порядок вычислений оговорен очень строго.
Оставить комментарий
Имя или ник:
Комментарий: