Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / странный ход выполнения / 22 сообщений из 22, страница 1 из 1
17.05.2020, 22:02
    #39958696
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
Всем привет.
Итак , упростил свой код по максимуму теперь он выглядит так и работает он как-то непонятно .
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
#include <cctype>   
#include <stdlib.h> 
#include <stdio.h>  


#define MAXOP 100  
#define NUMBER '0' 
#define MAXVAL 100 

int getop(char** source, char s[]);


int main(int argc, char* argv[])
{
    int type;
    double op2;
    char s[MAXOP];
    while (--argc > 0 && (*++argv)[0] != '\0'){
        while ((type = getop(argv, s)) != EOF) {
            
        }
           
        }
    return 0;
}
int getop(char** source, char s[])
{
    
    return NUMBER;
}



при пошаговом выполнении наблюдаю всё ход выполнения в main идет нормально до тех пор пока мы не доходим до второго цикла while , а затем - чудеса .По идее мы должны провалиться в getop, а мы мигом выскакиваем на return 0.
Помогите разобраться почему так происходит.
...
Рейтинг: 0 / 0
17.05.2020, 22:09
    #39958697
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81(*++argv)[0]

Это что за бред?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
17.05.2020, 22:14
    #39958698
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
Dimitry Sibiryakov

andron81(*++argv)[0]

Это что за бред?


это его величество Керниган ))
возможно сейчас гуру пишет вот так **++argv

так как argv это массив строк то (*++argv)[0] это перебор по каждому параметру , причем берем только первую букву ([0]).
...
Рейтинг: 0 / 0
17.05.2020, 22:20
    #39958700
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81,

С какими параметрами ты запускаешь программу? Вот тут:

Код: plaintext
1.
(*++argv)[0]


Смотри сначала ты префиксно переходишь к следующему аргументу. И получаешь "char *". Потом ты указатель разыменовываешь и получаешь "char". Потом ты с символом оперируешь как с указателем. Я вообще сомневаюсь что это должно компилироваться.

Попробуй так:

Код: plaintext
1.
(++argv) != NULL
...
Рейтинг: 0 / 0
17.05.2020, 22:23
    #39958701
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81
Dimitry Sibiryakov

пропущено...

Это что за бред?


это его величество Керниган ))
возможно сейчас гуру пишет вот так **++argv

Позволь тебе предложить подход.

Когда тебе что-то непонятно - ты берешь непонятный код и упрощаешь.
До тех пор пока не станет понятно.

Делаешь эквивалентные преобразования. Пред-и-пост инкременты - заменяешь
на операцию и инкремент. Иначе выглядит так как будто ты - вьI36щик. А тыж не
такой. Верно?

В туловище цикла - вставь какую-то нейтральную операцию типа printf
и поставь на нее брейкпоинт чтоб было понятно состояние цикла и что внутри.

Ведь цикл делается именно ради тела цикла. Верно?
...
Рейтинг: 0 / 0
17.05.2020, 22:28
    #39958702
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
petrav
andron81,

С какими параметрами ты запускаешь программу? Вот тут:

Код: plaintext
1.
(*++argv)[0]



вот такие параметры
20 3 4 + *

petrav

Смотри сначала ты префиксно переходишь к следующему аргументу. И получаешь "char *".


да потому что 0 параметр как я понимаю это имя моей программы.

petrav

Попробуй так:
Код: plaintext
1.
(++argv) != NULL





попробую , но думаю не в этом суть. главное что условие выполняется. а NULL там будет или '\0' уже другой вопрос.
Код: plaintext
1.
(--argc > 0 && (*++argv)[0] != '\0')


Но попробую !
...
Рейтинг: 0 / 0
17.05.2020, 22:31
    #39958703
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81,

Плохо ты книгу читал. :)
...
Рейтинг: 0 / 0
17.05.2020, 22:42
    #39958704
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
mayton
andron81
пропущено...


это его величество Керниган ))
возможно сейчас гуру пишет вот так **++argv

Позволь тебе предложить подход.

Когда тебе что-то непонятно - ты берешь непонятный код и упрощаешь.
До тех пор пока не станет понятно.

Делаешь эквивалентные преобразования. Пред-и-пост инкременты - заменяешь
на операцию и инкремент. Иначе выглядит так как будто ты - вьI36щик. А тыж не
такой. Верно?

В туловище цикла - вставь какую-то нейтральную операцию типа printf
и поставь на нее брейкпоинт чтоб было понятно состояние цикла и что внутри.

Ведь цикл делается именно ради тела цикла. Верно?


верно то верно. скорректировал код . Но есть тело или нет во внутреннем цикле загадка для меня каким образом цикл может щелкать сразу же к ретурну по кнопке F11 (VS) находясь на внутреннем вайле . то есть отладчиком дохожу до 2-го вайла , а затем нажимаю F11 и тут же оказываюсь на ретурне функции main. ведь даже если предположить , что условие не выполнилось внутреннего цикла (что тоже странно ведь для этого мы должны зайти в getop, а этого не происходит), то оказаться мы должны никак не в конце main.
А если я вообще удалю внутренний цикл тогда всё логично работает . просто произойдет перебор аргументов. то есть к ретурну компилятор переходить не спешит :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
int main(int argc, char* argv[])
{
    int type;
    double op2;
    char s[MAXOP];
    while (--argc > 0 && (*++argv)[0] != '\0'){
        
        while ((type = getop(argv, s)) != EOF) {
            argc = argc;
        }
        
        
        }
    return 0;
}
...
Рейтинг: 0 / 0
17.05.2020, 22:43
    #39958705
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81

вот такие параметры
20 3 4 + *

А это что типа калькулятор в польской записи?
Код: plaintext
1.
20 3 4 + * == 140


В советском программируемом калькуляторе МК-52 была такая. Я на нём в школе мастерски программировал.
...
Рейтинг: 0 / 0
17.05.2020, 22:44
    #39958707
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
petrav
andron81

вот такие параметры
20 3 4 + *

А это что типа калькулятор в польской записи?
Код: plaintext
1.
20 3 4 + * == 140


В советском программируемом калькуляторе МК-52 была такая. Я на нём в школе мастерски программировал.


да . это калькулятор выражений польской записи.
...
Рейтинг: 0 / 0
17.05.2020, 22:58
    #39958709
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
petrav
andron81,

Плохо ты книгу читал. :)


да ну ??? Если я допустил где-то ошибки, то и укажи мне на них. что я написал тут неправильно ?
...
Рейтинг: 0 / 0
17.05.2020, 23:01
    #39958710
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
petrav
andron81,

С какими параметрами ты запускаешь программу? Вот тут:

Код: plaintext
1.
(*++argv)[0]


Смотри сначала ты префиксно переходишь к следующему аргументу. И получаешь "char *". Потом ты указатель разыменовываешь и получаешь "char". Потом ты с символом оперируешь как с указателем. Я вообще сомневаюсь что это должно компилироваться.

Попробуй так:

Код: plaintext
1.
(++argv) != NULL


Да, это я ерунды наговорил ближе к ночи. :) Сейчас разберусь, пардон
...
Рейтинг: 0 / 0
17.05.2020, 23:11
    #39958711
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
Код конечно далёк от совершенства, но он работает.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
int getop(char** source, char s[])
{
    return EOF;
}

int main(int argc, char* argv[])
{
    int type = 0;
    double op2 = 0.0;
    char s[1024] = "";
    while (--argc > 0 && (*++argv) != NULL)
    {
        while ((type = getop(argv, s)) != EOF)
        {
        }
    }
}


В первом while второе условие лишние.
...
Рейтинг: 0 / 0
17.05.2020, 23:16
    #39958712
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
Я не знаю. Этот код наверно надо вешать в качестве примера того
как писать не надо. Безотносительно что там писал Кернинган. Его
время прошло. И мутировать аргументы - это code-smell. По идее
статик анализаторы здесь должны ругнуться.

Грубо говоря если тебе зашел аргумент argc - то рассматривай его
как константу. Крути какие угодно циклы но этот парамтер не трогай.

Вот как-то так.
Код: plaintext
1.
2.
3.
for(int i = 0; i < argc; i++) {
    printf("Argument %d is %s\n", i, argv[i]);
}



Существует также некая разумная метрика. Количество операторов
на 1 строку кода. И когда ты пишешь такое

Код: plaintext
1.
--argc > 0 && (*++argv)[0] != '\0'



То в этом коде плохо ходить дебаггером. Т.к. в нем происходит слишком
много всего. И проверки и мутации и разные сайд-эффекты. И программисту
если надо трабл-шутить какой-то дефект или ошибку - придется все равно
разваливать эту длинную строку на хотя-бы 4-5 атомарных строк смысл
которых будет виден под отладчиком.

И в командной разработке тех-лид должен не пропустить такой код.
...
Рейтинг: 0 / 0
17.05.2020, 23:26
    #39958714
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
petrav

В первом while второе условие лишние.

Только, конечно, просто так удалять его не нужно. Там побочный эффект. Инкрементацию нужно в тело цикла перенести.
...
Рейтинг: 0 / 0
17.05.2020, 23:36
    #39958716
mini.weblab
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81,
все нормально проваливается
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
int getop(char** source, char s[])
{
    return '0';
}

int main(int argc, char **argv) {
    int test;
    while (--argc > 0 && (*++argv)[0] != '\0'){
        while ( (test = getop(argv, "Hello")) != EOF ) {}
        return 10;
    }
    return 0;
}
...
Рейтинг: 0 / 0
18.05.2020, 00:53
    #39958721
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
andron81загадка для меня каким образом цикл может щелкать сразу же к ретурну по кнопке F11 (VS)
находясь на внутреннем вайле

Это называется оптимизация. Компилятор выкидывает код, который ничего не делает, потом
код, результат которого нигде не используется. То, что останется, тасуется так как удобнее
исполнять. В результате пошаговый отладчик становится бесполезным чуть более чем полностью.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
18.05.2020, 08:16
    #39958762
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
Dimitry Sibiryakov

andron81загадка для меня каким образом цикл может щелкать сразу же к ретурну по кнопке F11 (VS)
находясь на внутреннем вайле

Это называется оптимизация. Компилятор выкидывает код, который ничего не делает, потом
код, результат которого нигде не используется. То, что останется, тасуется так как удобнее
исполнять. В результате пошаговый отладчик становится бесполезным чуть более чем полностью.


всё же это похоже на глюк. эту же исходную программу я сохранил вчера в текстовик и на другом компе сегодня его открыл и всё стало работать логично и закономерно проваливается в функцию getop().
у меня это бывало и раньше, и заметил , что всегда это проскакивает, когда код копипастишь из pdf версии книги. может какой-то мусор копируется дополнительно.
...
Рейтинг: 0 / 0
18.05.2020, 08:25
    #39958767
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
mayton


Грубо говоря если тебе зашел аргумент argc - то рассматривай его
как константу. Крути какие угодно циклы но этот парамтер не трогай.



согласен , учту .

mayton

Существует также некая разумная метрика. Количество операторов
на 1 строку кода. И когда ты пишешь такое

Код: plaintext
1.
--argc > 0 && (*++argv)[0] != '\0'



То в этом коде плохо ходить дебаггером. Т.к. в нем происходит слишком
много всего. И проверки и мутации и разные сайд-эффекты. И программисту
если надо трабл-шутить какой-то дефект или ошибку - придется все равно
разваливать эту длинную строку на хотя-бы 4-5 атомарных строк смысл
которых будет виден под отладчиком.
И в командной разработке тех-лид должен не пропустить такой код.


мне тем более как дилику выносит мозг, когда в условии цикла происходит всякие там *++argv. я бы тоже вынес это в тело.
тоже думал , что для отладки это не пригодно. но так же думал, что надо привыкать к такому стилю.
Принято, спасибо
...
Рейтинг: 0 / 0
18.05.2020, 10:39
    #39958806
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
Игры с пред-пост инкрементом - это старый стиль. Его природа уходит корнями в ассемблер.
Тоесть грубо говоря - не дружит с человеческим языком и математикой.

Еще визуальной сложности может подбросить цикл for где в итерационном выражении
программит играется с итерационным выражением. Переставляя плюсик то слева то справа.
Это подкидывает больше WTF на код-ревью.

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

Тоесть как-только у тебя возникает подозрение на UB - тут-же выбрасывай из выражения инкременты
либо до выражения либо после в зависимости от того где стоит двойной плюсик.

Есть даже забавные мозговыносящие вопросы на собеседовании как раз связанные с UB
в выражении где есть и использование переменной несколько раз и ее-же инкременты.

Вот у нас было

https://www.sql.ru/forum/1130056/poryadok-vychisleniya
https://www.sql.ru/forum/1309184-2/chto-neopredelyonnogo-v-c-c
...
Рейтинг: 0 / 0
18.05.2020, 13:11
    #39958881
mini.weblab
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
кстати, непонятно причем здесь UB, и хотелось бы увидеть пример ...
...
Рейтинг: 0 / 0
18.05.2020, 13:20
    #39958885
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
странный ход выполнения
В данном примере конкретно UB я не вижу. Это было просто комментарий
к такому стилю кодирования

Код: plaintext
1.
--argc > 0 && (*++argv)
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / странный ход выполнения / 22 сообщений из 22, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]