Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
number_118
6 / 6 / 1
Регистрация: 28.09.2018
Сообщений: 390
1

Похоже, задача на приоритет

22.02.2019, 20:15. Просмотров 2568. Ответов 18

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <conio.h>
 
int main (void) {
    
    int a = 5, tmp1;
    
    printf("a = %d\t++a = %d\ta++ = %d\n", a, ++a, a++ );
    /*printf("Сработал ли постфиксный инкремент aka a++ ?\n");
    printf("%s", a - 1 == tmp1 ? "Да." : "Нет.");*/
    getch();
    return 0;
    
}
Название: Screenshot_4.png
Просмотров: 30

Размер: 7.3 Кб

Я так понял, тут сработал некий приоритет: сначала сработали оба инкремента, затем - printf. Но любопытно, почему первое и второе даже выдаёт 7, а третье = 5...

Спасибо.
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.02.2019, 20:15
Ответы с готовыми решениями:

Похоже, на АП PR
Вроде рано, но у меня поменялись значения. Морда с 3 до 2 упала, зато 2 внутренние страницы...

Похоже попал
Всем здравия прям побольше во все органы Вовечно. Тут у меня вскочил вопрос. Практически на 100 %...

Похоже, на вирус
решил на всякий случай проверить на вирусы. спасибо

Похоже на брак
Сегодня купил видеокарту gtx 660 asus, все бы хорошо, но после 2ух часов работы курсор стал...

похоже на вирус
Что это может быть-само запускаеться и что-то скачивает?

18
Байт
Эксперт C
21154 / 13345 / 2808
Регистрация: 24.12.2010
Сообщений: 28,137
22.02.2019, 20:23 2
Цитата Сообщение от number_118 Посмотреть сообщение
тут сработал некий приоритет
Ерунда. Никаких секретов и приоритетов нет. Просто a++ - сначала используется, а потом добавляется. ++a - сначала добавляется, потом используется.
Просмотр идет слева направо.
0
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
22.02.2019, 21:15 3
Лучший ответ Сообщение было отмечено number_118 как решение

Решение

Цитата Сообщение от Байт Посмотреть сообщение
Ерунда. Никаких секретов и приоритетов нет. Просто a++ - сначала используется, а потом добавляется. ++a - сначала добавляется, потом используется.Ерунда. Никаких секретов и приоритетов нет. Просто a++ - сначала используется, а потом добавляется. ++a - сначала добавляется, потом используется.
Просмотр идет слева направо.
Действительно ерунда. В Си есть такое понятие "точка следования" (sequence point). в рамках одной точки следования компилятор в праве перемешать код как угодно. Запятая при перечислении аргументов ф-ции не является оператором и не гарантирует порядок _вычисления_ аргументов. Т.е. вместо 7 7 5 там может оказаться и 5 6 6.

Up: Не проверял, конкретно этот пример, но на 99% уверен, что gcc и clang дадут разный результат.
1
number_118
6 / 6 / 1
Регистрация: 28.09.2018
Сообщений: 390
22.02.2019, 21:22  [ТС] 4
Байт, я знаю, честно

Взглянем внимательнее на

C
1
2
3
int a = 5, tmp1;
    
    printf("a = %d\t++a = %d\ta++ = %d\n", a, ++a, a++ );
Невольно возникает вопрос: не должно ли выводиться:

Код
a = 5     ++a = 6     a++ = 6
Ср.:

Код
a = 7     ++a = 7     a++ = 5
Спасибо!

Добавлено через 3 минуты
prik, пока писал, Вы повторили мою мысль...
Неужели эта "точка следования", странная и неведомая... Надо будет изучить.
0
22.02.2019, 21:22
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
22.02.2019, 21:39 5
Лучший ответ Сообщение было отмечено number_118 как решение

Решение

Цитата Сообщение от number_118 Посмотреть сообщение
Неужели эта "точка следования", странная и неведомая... Надо будет изучить.
Почему "неведомая" их всего примерно полтора десятка в языке.

Добавлено через 7 минут
Википедия по этому поводу https://ru.wikipedia.org/wiki/%D0%A2...5_C_%D0%B8_C++ если неохота ковырять стандарт
0
Байт
Эксперт C
21154 / 13345 / 2808
Регистрация: 24.12.2010
Сообщений: 28,137
22.02.2019, 21:49 6
Цитата Сообщение от prik Посмотреть сообщение
Не проверял, конкретно этот пример, но на 99% уверен, что gcc и clang дадут разный результат.
Попробуйте. Результаты эксперимента опубликуйте, пожалуйста.
Однако, я всегда считал, что в запятой нет никаких секретов. А просто последовательное выполнение, и больше ничего. Но настаивать я не буду. Не являясь большим знатоком стандартов. Просто, мне это кажется логичным. А логике создателей языка, как и логике его модификаторов, я привык доверять. И непонятно, зачем на ровном месте создавать UB. Делать что ли больше нечего?
0
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
22.02.2019, 22:02 7
Цитата Сообщение от Байт Посмотреть сообщение
Попробуйте. Результаты эксперимента опубликуйте, пожалуйста.
Переборол лень. хоть в чем-то
Кликните здесь для просмотра всего текста
-bash-4.4$ cat seqp.c
#include <stdio.h>

int main (void) {
int a = 5;
printf("a = %d\t++a = %d\ta++ = %d\n", a, ++a, a++);
return 0;
}
-bash-4.4$ gcc -W -Wall -oseqp.gcc seqp.c
seqp.c: In function 'main':
seqp.c:5: warning: operation on 'a' may be undefined
seqp.c:5: warning: operation on 'a' may be undefined
-bash-4.4$ clang -W -Weverything -oseqp.clang seqp.c
seqp.c:5:47: warning: unsequenced modification and access to 'a' [-Wunsequenced]
printf("a = %d\t++a = %d\ta++ = %d\n", a, ++a, a++);
~ ^
1 warning generated.
-bash-4.4$ ./seqp.gcc
a = 7 ++a = 7 a++ = 5
-bash-4.4$ ./seqp.clang
a = 5 ++a = 6 a++ = 6
-bash-4.4$
1
Байт
Эксперт C
21154 / 13345 / 2808
Регистрация: 24.12.2010
Сообщений: 28,137
22.02.2019, 23:36 8
prik, Да, очень интересно... значит мои представления о разумности мира были ошибочны...
Спасибо Вам!
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10566 / 6267 / 1573
Регистрация: 25.07.2009
Сообщений: 11,936
23.02.2019, 00:31 9
Цитата Сообщение от Байт Посмотреть сообщение
Однако, я всегда считал, что в запятой нет никаких секретов.
Есть оператор "запятая", который выполняется всегда слева направо и возвращает последнее вычисленное значение. И есть параметры функции, которые между собой никак не связаны, просто пишутся через запятую. Порядок их вычисления не определён. Фактически они могут вычисляться в любом порядке, как разработчикам компилятора их странный бог на душу положит. Поэтому рассчитывать на какой-то определённый результат в подобных выражениях не приходится.
1
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
23.02.2019, 16:02 10
Нашелся еще 1 вариант (родной сановский компилятор):
Bash
1
a = 7   ++a = 6 a++ = 6
easybudda, не знаю, верно ли тут делать акцент именно на операторе запятая vs запятая как разделитель списка параметров.
Я бы просто сказал, что менять переменную несколько раз в рамках одной точки следования нельзя.
Цитата Сообщение от Байт Посмотреть сообщение
Делать что ли больше нечего
Смотрите на это с позиции "каждое жесткое ограничение == заставляем компилятор генерировать определенный (часто ненужный/неэффективный) код == потеря производительности".
0
Байт
Эксперт C
21154 / 13345 / 2808
Регистрация: 24.12.2010
Сообщений: 28,137
23.02.2019, 16:08 11
Как бы то ни было, в серьезной работе применять конструкции типа показанных в стартовом посте я не применял, и не собираюсь применять в дальнейшем. И никому не советую.
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10566 / 6267 / 1573
Регистрация: 25.07.2009
Сообщений: 11,936
23.02.2019, 16:25 12
Цитата Сообщение от prik Посмотреть сообщение
не знаю, верно ли тут делать акцент именно на операторе запятая
Ну на поведение оператора всё-таки можно рассчитывать.... Не вдаваясь в странность происходящего (и списав её на лень заняться чем-то полезным):
C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
int main(void) {
    int a, b, c;
 
    a = 5, b = ++a, c = a++;
    printf("%d %d %d\n", a, b, c);
 
    return 0;
}
Код
[andrew@easybook numbers]$ gcc -Wall abc.c 
[andrew@easybook numbers]$ ./a.out 
7 6 6
[andrew@easybook numbers]$ clang -Wall abc.c 
[andrew@easybook numbers]$ ./a.out 
7 6 6
[andrew@easybook numbers]$
Вот ещё:
Похоже, задача на приоритет
0
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
23.02.2019, 16:36 13
Цитата Сообщение от easybudda Посмотреть сообщение
Ну на поведение оператора всё-таки можно рассчитывать....
Так и на оператор "вызов ф-ции" то же можно рассчитывать... Вы же не пытаетесь в своем тесте написать что-то типа
C
1
a=0, a = a++, b = ++a + a++;
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10566 / 6267 / 1573
Регистрация: 25.07.2009
Сообщений: 11,936
23.02.2019, 17:16 14
Цитата Сообщение от prik Посмотреть сообщение
Вы же не пытаетесь...
Не пытаюсь. Как-раз потому, что
Цитата Сообщение от prik Посмотреть сообщение
в рамках одной точки следования компилятор в праве перемешать код как угодно
Вот тут
Цитата Сообщение от prik Посмотреть сообщение
++a + a++
что будет вычислено первым, ++а или а++?

А вообще полностью согласен с Байт,
Цитата Сообщение от Байт Посмотреть сообщение
Как бы то ни было, в серьезной работе применять конструкции типа показанных в стартовом посте я не применял, и не собираюсь применять в дальнейшем. И никому не советую.
0
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
23.02.2019, 17:17 15
Цитата Сообщение от easybudda Посмотреть сообщение
что будет вычислено первым, ++а или а++?
UB. Точно так же как и a=a++;
Я просто не понял, к чему вы показали этот тест. Это просто был совет как обходить проблему или что-то другое?
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10566 / 6267 / 1573
Регистрация: 25.07.2009
Сообщений: 11,936
23.02.2019, 17:22 16
Цитата Сообщение от prik Посмотреть сообщение
к чему вы показали этот тест
Ну раз уж зашла речь про оператор "запятая" и порядок вычисления аргументов в функции (вернее его отсутствие), в операторе
Цитата Сообщение от easybudda Посмотреть сообщение
b = ++a
всегда будет вычисляться перед
Цитата Сообщение от easybudda Посмотреть сообщение
c = a++
0
prik
281 / 184 / 61
Регистрация: 01.03.2011
Сообщений: 501
23.02.2019, 17:56 17
Цитата Сообщение от easybudda Посмотреть сообщение
А вообще полностью согласен с Байт,
Я бы сказал, что врага надо знать в лицо, а не боятся чего-то интуитивно. Это примитивный/очевидный случай. Такие косяки встречаются и во "взрослом" коде например в виде foo(a(), b(), c()) когда между a() b() c() есть какие-то сайд-эффекты. Да и вообще, чего можно требовать от языка, где нельзя просто взять и сложить два int без риска получить UB

Добавлено через 27 минут
Кстати, вспомнилось... когда-то давно натыкался на сайте gcc или clang на список самых часто открываемых в их багтрекере багов компилятора, не являющихся багом. 1е место было за округлением float, а 2е почетное место, как раз за всевозможными вариациями a=a++ - учитывая, что баги на компилятор как правило вешают люди не в 1й раз увидевшие Си - в наших рядах сишников все печально и плохо.
0
easybudda
23.02.2019, 18:47
  #18

Не по теме:

Цитата Сообщение от prik Посмотреть сообщение
баги на компилятор как правило вешают люди не в 1й раз увидевшие Си
С завидным постоянством на самых разных ресурсах, включая и cyberforum, и stackoverflow, встречаются темы в духе "тупой компилятор не компилирует мой супер-код". При чём, если "супер-код" приложен, то в нём ошибок, как у дурака махорки. Самые из таких одарённые и до баг-траков добираются... Не так всё плохо, их не легион, от них шума больше...

0
prik
23.02.2019, 19:12     Похоже, задача на приоритет
  #19

Не по теме:

easybudda, сложный вопрос, вроде и да, а с другой стороны сишный код не вылезающий из bagtraq по одним и тем же симптомам о чем-то и говорит... Ну да это совсем уже лирика.

0
23.02.2019, 19:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.02.2019, 19:12
Привет! Вот еще темы с ответами:

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

Похоже Ап Google PP?
На всех сайтах ПР стал 0

Похоже на конфликт js?
Привет! Есть сайт http://piterka.sarmo.ru/ Недавно сделал ротатор баннеров (с которым пришлось...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru