Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
 странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
Всем привет.
Итак , упростил свой код по максимуму теперь он выглядит так и работает он как-то непонятно .
#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.
Помогите разобраться почему так происходит.
17 май 20, 22:02    [22134683]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50076

andron81
(*++argv)[0]

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

Posted via ActualForum NNTP Server 1.5

17 май 20, 22:09    [22134684]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
Dimitry Sibiryakov

andron81
(*++argv)[0]

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


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

так как argv это массив строк то (*++argv)[0] это перебор по каждому параметру , причем берем только первую букву ([0]).

Сообщение было отредактировано: 17 май 20, 22:18
17 май 20, 22:14    [22134685]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
petrav
Member

Откуда:
Сообщений: 2118
andron81,

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

(*++argv)[0]

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

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

(++argv) != NULL
17 май 20, 22:20    [22134689]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
mayton
Member

Откуда: loopback
Сообщений: 46600
andron81
Dimitry Sibiryakov

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

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


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

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

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

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

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

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

Сообщение было отредактировано: 17 май 20, 22:22
17 май 20, 22:23    [22134690]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
petrav
andron81,

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

(*++argv)[0]


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

petrav

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


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

petrav

Попробуй так:
(++argv) != NULL




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

Но попробую !
17 май 20, 22:28    [22134693]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
petrav
Member

Откуда:
Сообщений: 2118
andron81,

Плохо ты книгу читал. :)
17 май 20, 22:31    [22134694]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
mayton
andron81
пропущено...


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

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

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

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

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

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


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

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;
}


Сообщение было отредактировано: 17 май 20, 22:49
17 май 20, 22:42    [22134696]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
petrav
Member

Откуда:
Сообщений: 2118
andron81

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

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

В советском программируемом калькуляторе МК-52 была такая. Я на нём в школе мастерски программировал.
17 май 20, 22:43    [22134697]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
petrav
andron81

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

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

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


да . это калькулятор выражений польской записи.
17 май 20, 22:44    [22134700]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
petrav
andron81,

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


да ну ??? Если я допустил где-то ошибки, то и укажи мне на них. что я написал тут неправильно ?
17 май 20, 22:58    [22134702]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
petrav
Member

Откуда:
Сообщений: 2118
petrav
andron81,

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

(*++argv)[0]

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

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

(++argv) != NULL

Да, это я ерунды наговорил ближе к ночи. :) Сейчас разберусь, пардон
17 май 20, 23:01    [22134704]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
petrav
Member

Откуда:
Сообщений: 2118
Код конечно далёк от совершенства, но он работает.

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 второе условие лишние.
17 май 20, 23:11    [22134708]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
mayton
Member

Откуда: loopback
Сообщений: 46600
Я не знаю. Этот код наверно надо вешать в качестве примера того
как писать не надо. Безотносительно что там писал Кернинган. Его
время прошло. И мутировать аргументы - это code-smell. По идее
статик анализаторы здесь должны ругнуться.

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

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


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

--argc > 0 && (*++argv)[0] != '\0'


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

И в командной разработке тех-лид должен не пропустить такой код.
17 май 20, 23:16    [22134709]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
petrav
Member

Откуда:
Сообщений: 2118
petrav

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

Только, конечно, просто так удалять его не нужно. Там побочный эффект. Инкрементацию нужно в тело цикла перенести.
17 май 20, 23:26    [22134714]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
andron81,
все нормально проваливается
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;
}
17 май 20, 23:36    [22134717]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50076

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

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

Posted via ActualForum NNTP Server 1.5

18 май 20, 00:53    [22134727]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
Dimitry Sibiryakov

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

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


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

Сообщение было отредактировано: 18 май 20, 08:15
18 май 20, 08:16    [22134773]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
andron81
Member

Откуда: Смоленск
Сообщений: 834
mayton


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



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

mayton

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

--argc > 0 && (*++argv)[0] != '\0'


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


мне тем более как дилику выносит мозг, когда в условии цикла происходит всякие там *++argv. я бы тоже вынес это в тело.
тоже думал , что для отладки это не пригодно. но так же думал, что надо привыкать к такому стилю.
Принято, спасибо

Сообщение было отредактировано: 18 май 20, 08:23
18 май 20, 08:25    [22134778]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
mayton
Member

Откуда: loopback
Сообщений: 46600
Игры с пред-пост инкрементом - это старый стиль. Его природа уходит корнями в ассемблер.
Тоесть грубо говоря - не дружит с человеческим языком и математикой.

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

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

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

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

Вот у нас было

https://www.sql.ru/forum/1130056/poryadok-vychisleniya
https://www.sql.ru/forum/1309184-2/chto-neopredelyonnogo-v-c-c
18 май 20, 10:39    [22134836]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
кстати, непонятно причем здесь UB, и хотелось бы увидеть пример ...
18 май 20, 13:11    [22134961]     Ответить | Цитировать Сообщить модератору
 Re: странный ход выполнения  [new]
mayton
Member

Откуда: loopback
Сообщений: 46600
В данном примере конкретно UB я не вижу. Это было просто комментарий
к такому стилю кодирования

--argc > 0 && (*++argv)
18 май 20, 13:20    [22134966]     Ответить | Цитировать Сообщить модератору
Все форумы / C++ Ответить