powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / странный ход выполнения
22 сообщений из 22, страница 1 из 1
странный ход выполнения
    #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
странный ход выполнения
    #39958697
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81(*++argv)[0]

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

andron81(*++argv)[0]

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


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

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

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

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


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

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

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

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

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


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

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

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

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

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

Ведь цикл делается именно ради тела цикла. Верно?
...
Рейтинг: 0 / 0
странный ход выполнения
    #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
странный ход выполнения
    #39958703
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

Плохо ты книгу читал. :)
...
Рейтинг: 0 / 0
странный ход выполнения
    #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
странный ход выполнения
    #39958705
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81

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

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


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

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

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


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


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

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


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

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

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


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

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

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


Да, это я ерунды наговорил ближе к ночи. :) Сейчас разберусь, пардон
...
Рейтинг: 0 / 0
странный ход выполнения
    #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
странный ход выполнения
    #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
странный ход выполнения
    #39958714
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petrav

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

Только, конечно, просто так удалять его не нужно. Там побочный эффект. Инкрементацию нужно в тело цикла перенести.
...
Рейтинг: 0 / 0
странный ход выполнения
    #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
странный ход выполнения
    #39958721
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81загадка для меня каким образом цикл может щелкать сразу же к ретурну по кнопке F11 (VS)
находясь на внутреннем вайле

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

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

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


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


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



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

mayton

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

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



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


мне тем более как дилику выносит мозг, когда в условии цикла происходит всякие там *++argv. я бы тоже вынес это в тело.
тоже думал , что для отладки это не пригодно. но так же думал, что надо привыкать к такому стилю.
Принято, спасибо
...
Рейтинг: 0 / 0
странный ход выполнения
    #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
странный ход выполнения
    #39958881
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати, непонятно причем здесь UB, и хотелось бы увидеть пример ...
...
Рейтинг: 0 / 0
странный ход выполнения
    #39958885
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В данном примере конкретно UB я не вижу. Это было просто комментарий
к такому стилю кодирования

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


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