• Undefined behavior в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Скомпилирует любой компилятор с++. Может выдать ворнинги, если включена опция реагировать на предупреждения, как на ошибки, то тогда не скомпилирует, но только потому что его конкретно об этом попросили. Это не ошибка компиляции.

    В этом главная проблема Undefined Behavior: компилятор его почти всегда не видит, и программа с ним может даже работать в каких-то случаях так, как программист задумывал. А в других совершенно необъяснимо падает или выдает бред.

    У ОС защита от такой наглости с памятью, конечно, есть. Такая программа рано или поздно упадет с access violation, segmentation fault или еще чем-то подобным, когда цикл дойдет до не вашей памяти.
    Ответ написан
    Комментировать
  • Откуда появляется это странное число?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Читайте код внимательно:
    Ввод:
    for (int i=0; i<x; i++){

    Вывод:
    for (int i = 0; i <= x; i++){

    У вас там <= в конце. Из-за этого идет обращение к элементу по индексу x, за границей массива. И оттуда выводится какой-то мусор - это и есть ваше странное число.
    Ответ написан
    Комментировать
  • Как исправить баги в коде?

    mayton2019
    @mayton2019
    Bigdata Engineer
    И есть ли тут ещё какие-либо баги которые я сразу не заметил?

    Это очень интересный вопрос. На мильон я-бы сказал.

    Вообще если на программу не написана спецификация или тесты то тогда совершенно
    невозможно точно утверждать является ли поведение багом или так задумал автор.
    Я вот к стыду не помню всех правил морского боя. Что там с кораблем. Когда он затонет?
    Как мы узнаем что поражены все части корабля?

    Глядя на код трудно сказать где там ошибка. Надо его запускать. А запуск связан с вводом
    выводом. Тоесть нужно потратить много человеко-часов вводя буквы и цифры и симулируя
    разные игровые кейсы. Сам понимаешь нет такого энтузиаста который бы осилил за ништяк
    тестировать.

    Поэтому по возможности напиши тестовый код (в соотношении хотя-бы 1:10) чтобы он тестировал
    автоматически основной код. Есть такая практика. Модульное тестирование.

    По поводу сохранения игры - посмотри что сохраняется в внешний файл.
    Ответ написан
    Комментировать
  • Почему консоль всегда выводит, что я програл?

    @rPman
    c = rand() % 2;у тебя тут ошибка, c у тебя равно символу с кодом либо 0 либо 1,
    if (u == c)
    а сравниваешь с символом '0' либо '1', у них код 48 и 49 соответственно

    поэтому добавляй к c еще код символа '0' (он в ascii кодировке перед '1')
    c = rand() % 2+'0';
    p.s. из-за исторических наслоений, символ не считается несовместимым типом с числом, иначе бы ты увидел эту ошибку в сообщениях компилятора
    Ответ написан
    Комментировать
  • Ошибка в коде C++.?

    GavriKos
    @GavriKos
    Ну в целом ошибка сама за себя говорит. Нельзя в указатель записать символ.
    Ответ написан
    Комментировать
  • Как правильно сдвинуть биты?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Идея правильная, но битовые маски - нет. Чтобы взять a7 надо действительно сделать & 0x80. Но для a6 надо брать & 0x40. Потом идут 0x20, 0x10, 0x08, 0x04, 0x02, 0x01.

    Ваше 0x70 - это 0b01110000 - три бита вместо одного. Повторите 16-ричную систему счисления.
    Ответ написан
    1 комментарий
  • Хотел написать движок на OpenGL, а примитивная ходьба работает криво, как исправить?

    VoidVolker
    @VoidVolker
    Dark side eye. А у нас печеньки! А у вас?
    Дебажить, конечно же. Взять бумажку и ручку/планшет и стилус или что там есть под рукой, расписать по шагам весь алгоритм, сделать вывод результатов каждого шага алгоритма в коде и сравнить как должно быть и что получилось.
    Ответ написан
    2 комментария
  • Как передать в аргумент функцию, и выполнить её, передаваю в неё параметры?

    @dima20155
    you don't choose c++. It chooses you
    Самый простейший пример.
    Модифицируйте его если нужны ссылки на аргументы

    #include <functional>
    #include <iostream>
    
    template <typename Func, typename ... Args>
    void foo(Func func, Args ... args) {
        func(args...);
    }
    
    int main() {
        foo([](){ std::cout << "endl;" << std::endl; });
        foo([](int i){ std::cout << "int i: " << i << std::endl; }, 123);
    }
    Ответ написан
    Комментировать
  • Что стоит учить с или c++ или c#?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Добрый вечер! Столкнулся с такой проблемой: Мне очень нравятся семейство языков Си, у меня есть выбор учить C++ либо C#, хочу разрабатывать ПО для ПК. Подумал начать с C++ и говорят что сначала поучить чистый СИ, а после переходить на C++, так что же из этого правильно? Надо ли учить Си? Или может лучше начать с C#, а дальше уже выучу C++?

    Тема сравнения С/C++/C# в публичном пространстве - опасная тема. Она обычно заканчивается
    топиком в 1000 страниц и великой войной всех против всех. Я видел много таких войн.
    Они ничем не заканчиваются. Специалисты остаются при своих мнениях. А зритель просто развлекается.

    Сам по себе выбор языка ставят только новички. Професиионалу безразличен язык (почти). Его может больше интересует отрасль, стек технологий, стандарты и протоколы. С моей точки зрения сегодня
    таким стандартом может быть выбор облака (AWS, Azure, GCP).

    Чистый СИ учить смысла нет. Учи сразу С++. Но даже его создатель Бьорн Страуструп считает что С++ это
    сложный язык и он настаивает чтобы новички не брались учить все фичи сразу. Исключение по языку
    СИ может быть в том случае, если ты собрался быть инженером по разработке микро-контроллеров
    и у тебя скорее всего будет только СИ как основной (на 80-90%) инструмент взаимодействия с таким железом. Выйти на мидловый или синьорный уровень в С++ очень тяжело. Тяжелее чем в других языках.
    Поэтому будь готов терпеть. Вот когда виски станут седые - тогда и будешь господин-синьор.

    C# - это очень сильно корпоративный стандарт от Microsoft. Никакой связи с С++ он не имеет. Он конечно
    внешне похож но это сходство обманчиво. Да изучать его тоже можно. Он учится легко. Существуют книги
    вроде ".... C# за 14 дней". Разработка бизнес-приложений на шарпах идет гораздо быстрее чем на С++
    например. И завалить систему в синий экран в этом языке гораздо труднее. В нем реализованы методы
    защиты памяти и нельзя грязно трюкачить с указателями как это любят в С или С++. Производительность
    шарпов в численных методах будет слабее чем в С++ но обычно бизнес не ставит таких задач и чаще
    надо будет писать веб-хендлеры или хендлеры MQ-систем. Кач уровней синьорити идет быстрее в шарпах.
    Ответ написан
    2 комментария
  • Что стоит учить с или c++ или c#?

    AshBlade
    @AshBlade Куратор тега C#
    Просто хочу быть счастливым
    Это 3 совершенно различных, с точки зрения целей, языка. Лучше пойми что ТЫ хочешь, а потом выбери
    Ответ написан
    Комментировать
  • Как правильно реализовать освобождение памяти выделенной в функции?

    @dima20155
    you don't choose c++. It chooses you
    Все до безобразия просто:
    Вы выделяете память в момент, когда она вам нужна, а удаляете когда эта память вам более не нужна.
    Соотвественно, вам нужна функция array_deinit(), которая возьмет на себя непосильную ношу освобождения памяти в момент, когда вы больше не планируете обращаться к своему двумерному массиву.

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

    Также в современном С++ не принято использовать new/delete без веской причины (например, вы пишете супер быстрый, современный контейнер, в котором хотите управлять всеми аллокациями самостоятельно), а рекомендуется использовать умные указатели для работы с памятью.
    Ответ написан
    2 комментария
  • Почему нельзя использовать std::function как аргумет шаблонной функции?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Потому что лямбда не ялвяется std::function. Компилятор, вообще говоря, может лямбду привести к типу std::function, но не в вашем случае. Вам надо, например, самим преобразовать лямбду в std::function:
    std::function<bool(int, int)> comp = [](int left, int right)
      {
        return left < right;
      };
      Sort(vec, comp);


    Сам компилятор тут это сделать не может, потому что ему тип к которму приводить-то неизвестен - он зависит от параметра шаблона T.

    Можно, еще, например, указать компилятору параметры шаблона, тогда все скомпилируется:
    Sort<int>(vec, [](int left, int right)
      {
        return left < right;
      });


    Но лучший вариант - не использовать std::function в шаблоне. Просто используйте какой-то typename U, у которого вы продполагаете существует operator(int, int). Если туда передать не function и не лябмду, оно не скомпилится:

    template <typename T, typename U>
    void Sort(std::vector<T>& vector, U comparison) {
        // Используете comparison, как-будто это std::function:
        if (comparison(1, 1)) return;
    };
    
    
    int main()
    {
      std::vector<int> vec = { 1, 2, 3, 4, 5, 7, 6, 9 ,8 };
    
      Sort(vec, [](int left, int right) -> bool
      {
        return left < right;
      });
        return 0;
    }
    Ответ написан
    Комментировать
  • Почему умножение матрицы 8x8 медленнее чем 10x10?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Скорее всего тут дело в кеше процессора. После первых запусков так получилось, что данные оказались в кеше.

    Вообще, писать бенчмарки - очень сложно. Надо сначала прогонять тест несколько раз и отбрасывать результаты, а уже потом мерять. Надо быть очень внимательным, если вы запускакте разные тесты в одной программе подряд: результаты работы одного теста могут повлиять на остальные.

    Ну и главное, выполнять такое короткое действие всего один раз - это вообще моветон. Надо выполнить его сотню тысяч раз и потом общее время делить на количество запусков. Иначе вы меряете случайный шум в основном. Может тут вам просто все время (не)везет и вот так третий тест оказывается быстрее остальных.
    Ответ написан
    3 комментария
  • Как определить принадлежность точки к плоскости?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    У вас нет проверки условий для диагональных границ области: y<=x при x<=1 и abs(y)<=x-1 при x>=1. Добавляйте, проверяйте и сдавайте решение.
    Ответ написан
    1 комментарий
  • Не работает case в switch. Как решить проблему?

    @res2001
    Developer, ex-admin
    Блоки case в операторе switch это просто аналог меток для goto. Соответственно после перехода на какой-то case выполнение программы продолжается по всем строкам кода подряд. И если вы не предусмотрели явный выход из блока case (с помощью break или return), то выполнение продолжится и в следующем case и т.д.

    Современные компиляторы умеют выдавать ошибки или предупреждения для таких случаев, т.к. очень часто в коде действительно присутствует ошибка - пропуск оператора break или return (как у вас). В gcc для этого служит опция -Wimplicit-fallthrough. Иногда проваливание в следующий case бывает полезно и используется на практике программистами, тогда (при использовании опции -Wimplicit-fallthrough) надо явно указать на это компилятору. В документации gcc в описании этой опции указано как это сделать.

    Вообще рекомендую ужесточать проверки компилятора, как минимум с помощью стандартных опций: -Wall -Wextra.
    А так же указывать какому стандарту языка надо придерживаться компилятору: -std=c++17 или -std=gnuc++17
    Можно добавить и опцию: -pedantic
    По умолчанию многие полезные предупреждения отключены.
    Многие предупреждения можно перевести в ошибку или игнорировать.
    Есть и другие полезные проверки, которые может делать компилятор, которые не входят в -Wall -Wextra. Но для начала используйте хотя бы их.

    Описание опций предупреждений gcc смотри тут: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
    Ответ написан
    Комментировать
  • Как хранится struct в памяти?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Зависит от компилятора и заданных при компиляции опций. Например, при плотной упаковке (#pragma pack(1)) каждый элемент структуры занимает ровно столько, сколько ему необходимо. А при выравнивании на 64 бита (#pragma pack(8)) под каждый элемент выделится память, кратная 8 байтам и достаточная для размещения элемента. Для разных архитектур процессоров могут быть доступны разные настройки выравнивания.
    Ответ написан
    Комментировать
  • Почему не работает перемещение в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас полная каша в голове. Вы не понимаете, что такое перемещение, копирование.

    Вот как вы себе пердставляете перемещение int*?
    int* - это адрес в памяти. Число. Когда вы "перемещаете" img этого типа, вы перемещаете одно число. Из переменной img, в вектор.

    При этом что там лежит в памяти по адресу, равному этому числу (или на 20 сдвинутому), вообще не поменялось.

    Да, указатели используются в перемещении. Вместо того, чтобы копировать буффер в новое место. можно просто переприсвоить указатель в новой структуре на указатель в старой. Именно так вы перемещаете указатель, вместо копирования данных по этому адресу. Вот чем перемещение отличается от копирования.

    Так, у вас в imgs вы не пихаете копию данных, а пихаете указатель.
    Ответ написан
    2 комментария
  • Откуда взялся const?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    const char* взялся вот отсюда: "Hello world". Это строковая константа в коде. Ее программа менять никак не может. Компилятор ее засовывает в read only секцию исполняемого файла.
    Ответ написан
    Комментировать
  • Откуда взялся const?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Попробуй так.

    void printMessage(const char str[]);

    Чем новее становится версия стандарта С++ - тем строже проверки.
    Ответ написан
    Комментировать
  • Почему в С++ не работают 2 цикла for?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Ты наверное новичек?

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

    И не забывай инициализировать. И не забывай про scopes.

    for(int i = 0; i < n; i++) {...}

    Иногда профессионалы могут использовать переменную дважды для достижения какой-то другой
    цели. Тут надо смотреть use-case.

    Но Quod licet Iovi, non licet bovi. Тебе пока не позволено. Научись сначала просто
    писать код без ошибок а потом уже делай трюки.
    Ответ написан
    2 комментария