Задать вопрос
  • Как отключить окно при подключении по RDP Windows 11?

    1. Microsoft усилила защиту Windows от вредоносных RD...
    2. попробовать mRemoteNG или другие менеджеры подключений к удалённым системам
    Ответ написан
    1 комментарий
  • Почему при включённом dhcp после перезагрузки, пк пытается принять занятый ip-адрес?

    opium
    @opium
    Просто люблю качественно работать
    у меня примерно такая же история была — главный роутер раздаёт, а часть машин всё равно 169 получает. Оказалось промежуточные роутеры в NAT-режиме работали, делали отдельные подсети, броадкаст DHCP туда не проходит. Перевёл в режим точки доступа (кабель в LAN-порт, не в WAN, NAT выключить) — заработало.
    Ответ написан
    8 комментариев
  • Заголовочные файлы в Си нужны только для интерфейса?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Для того, чтобы использовать в main.c функцию, определенную в math_functions.c, вам надо иметь ее объявление в main.c

    Вам надо сказать компилятору, что вот такая функция есть и у нее вот такие вот параметры.

    Можно просто в main.c написать то, что вы бы написали в math_functions.h. Но это быстро становится сложно, если у вас проект большой и функции используются в разных файлах. Надо будет эти объявления копировать в кучу мест. А если вам еще и поменять что-то надо потом, вы офигеете. Для этого и придумали заголовочные файлы - вы пишите объявление один раз и потом его везде используете.

    Вообще, сейчас не обязательно math_functions.h включать и в math_functions.c. Раньше надо было определять функцию даже если ее объявления нигде нет. В современных стандартах это не так. Но все равно хедеры включают в соответствующий файл, чтобы ловить ошибки. Если вы поменяете функцию в .c но не поменяете в хедере, компилятор заметит несоответствие объявления и определения и сообщит об ошибке.
    Ответ написан
    6 комментариев
  • Заголовочные файлы в Си нужны только для интерфейса?

    @Mercury13
    Программист на «си с крестами» и не только
    Хедеры служат, чтобы два c-файла — они называются «единицы трансляции» — компилировались по отдельности. Это основное назначение той разновидности include-файлов, которые называются хедерами.

    Можно в h-файлы посадить и тела функций, только убедиться, что каждое тело ровно в одной единице трансляции — есть такой подход под названием «одна единица трансляции», и он существует у больших редко перекомпилируемых библиотек, чтобы перекомпиляция была покороче.

    Подключение main.c←math_functions.h служит, чтобы сказать компилятору: а где-то в другом месте есть эти функции.

    Подключение math_functions.c←math_functions.h — частично для подключения прочего общего вроде типов, частично для проверки на ошибки. Дело в том, что Си традиционно не козявит (does not mangle) имена функций, и если в хедере sin(int), а в реализации sin(double) — будут трудноуловимые ошибки.

    Да, деление на единицы компиляции решает и другую задачу — декомпизицию программы на меньшие элементы, и есть противоречие одного с другим (особенно в языке Си++, где хедеры огромны)

    В хедере находится только то, что не производит кода. Если говорить про Си++, то…
    • inline-объекты (код производят вызовы объекта)
    • определения типов, функций и прочего; extern-определения переменных (код производят тела функций и окончательные определения переменных)
    • шаблоны, если те нужны более чем в одной единице компиляции (код производит специализация)
    Но полные специализации шаблонов производят код и находятся в cpp-файле!
    Ответ написан
    Комментировать
  • Как найти причину недетерминизма программы?

    @kovserg
    "Она написана на C/C++ давно не мной" -> врядли она многопоточна или использует opencl / cuda.
    "Если запускать их по отдельности, но все хорошо" -> А ваша чудо программа создаёт временные файлы? Как вариант попробывать запускать разные копии программы в разных директориях.
    "Я его собрал в Debug моде и при таком использывании проблем нет" -> в коде UB, прогнать анализатор и valgrind
    "Как найти причину недетерминизма программы?" как обычно логированием этапов вычисления. Можно даже не самих данных а значения их hash значения (для уменльшения логов) и пологам искать место возникновения отклонений. После локализации смотреть причины.
    Ответ написан
    Комментировать
  • Как скомпилировать рабочую dll библиотеку?

    @igreklpofrss Автор вопроса
    Как оказалось не учел соглашение о вызовах.
    __cdecl: очищает стек после каждого вызова (add esp, X)
    __stdcall: очищает стек внутри функции(retn X)

    После добавления __stdcall в функцию crsGetString, компилятор теперь знает, что она самостоятельно очищает стек, поэтому функции GetMapDescriptions не надо заниматься его очисткой.
    typedef int (__stdcall *crsGetStringType)(void *, int, char *Destination, int Count);

    На Ассемблере проще писать, чем на С++ с учетом кучи тонкостей..
    Ответ написан
    1 комментарий
  • Почему при попытке сделать "git push" выдает ошибку?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    У вас проблемы в каждой команде.

    git commit -m "hw-EDU-9336"
    ...
    nothing to commit...

    — коммитить было нечего и коммит не создался. Но это не мешает делать push.

    6939b3c84ad34617699343.jpeg

    Совет: в любой непонятной ситуации смотрите git status. Смотрите его как до команд, так и после.

    git push
    ... The current branch ... has no upstream branch

    Здесь Git говорит, что текущая ветка не имеет связи ни с какой вышестоящей веткой. Git понятия не имеет, куда вы хотите пушить и что пушить.
    В общем случае команда выглядит примерно так:
    git push <репо_куда_пушить> <какую_ветку_пушить>

    Обычно при первой отправке мы просим гит создать связь локальной и вышестоящей веток.
    Гит подсказывает вам, как это сделать:
    git push --set-upstream origin hw-EDU-9336-sprint-1
    но можно написать проще, чтобы не мучиться запоминанием длинных названий:
    git push -b origin HEAD
    HEAD это синоним текущей ветки.

    Дальше у вас реальная ошибка. Скорее всего проблема в авторизации.

    Проверьте, что ключ действительно стучится в GitLab
    ssh -T git@gitlab.quality-academy.ru
    Успешный вариант: GitLab поздоровается и скажет, что логин найден.
    Неуспешный: "Permission denied (publickey)".

    И главное — публичный ключ должен быть добавлен в GitLab:
    User Settings → SSH Keys
    Если после этого Git продолжает упираться — значит просто нет прав на запись в репозиторий, а не проблема с ключами.
    Ответ написан
    2 комментария
  • Почему в ethtool не выводится информация о партнёре?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему в ethtool не выводится информация о партнёре?

    Не реализовано в драйвере. Информация о том, что предложил link partner берётся из поля lp_advertising структуры ethtool_cmd, см. Функция igb_get_link_ksettings это поле не заполняет, см. Вот пример функции, которая заполняет, см.
    Ответ написан
    Комментировать
  • Имя массива это адрес первого элемента или указатель на его первый элемент в Си?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    arrOne и arrTwo - это переменные, типов int[5] и int[3][2]. Это на уровне C. Под капотом там указатели: компилятор знает адрес начала массива. Путаницу может вызвать то, что массивы в языке C тождественны указателям на начало с той лишь разницей, что компилятор знает его длину и всякие sizeof() сработают правильно.
    Соответственно, arrOne неявно приводится к int*, а arrTwo к int (*)[2] (указатель на массив из 2 элементов, что в свою очередь неявно приводиться к указателю на указатель на инт).

    Поэтому работает код:
    int a[3][2];
       int (*b)[2];
       b = a;


    Можно считать, что arrOne - указатель на первый элемент int, а arrTwo - указатель на первую строку int[2], по совместительству на первый элемент в первой строке:
    int x = *arrOne;
       int y = **arrTwo; // с одной * не сработает ибо int[2], оно же int* к int не приводиться.
       int *z = arrOne+2; // указатель на 3-ий элемент
       int *w = arrTwo + 1; // указатель на вторую строку (первый элемент в ней).


    Но лучше на закапываться в адрессную арифметику, а воспринимать массивы, как свой отдельный тип данных. Не пишите arrOne+1, а пишите arrOne[1] и не парьтесь.

    Даже для int переменных компилятор знает их адрес, так что там под капотом тоже есть указатель. Не очень большая разница.

    Массив - это индексируемая область памяти. Единственное, о чем надо помнить, что массивы всегда передаются по ссылке. Их дешево передавать в функции и изменения массива внутри всегда видны снаружи.
    Ответ написан
  • Влияет ли, передаёшь ты в функцию аргументы по ссылке или по значению, на производительность и память?

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

    В целом, в С++ хорошее правило - передавать большие переменные как const &.

    Но для мелких типов, вроде int, передавать по ссылке может быть даже дороже, ибо и ссылка и значение тупо помещаются в регистр. Но ссылку надо будет еще разыменовывать, чтобы прочитать значение из памяти, а значение из регистра компилятор может даже не сохранять в память.

    С другой стороны, компилятор может наоптимизировать и даже ссылка на int будет не дороже копии int.

    Сразу говорить про все языки программиования нельзя. В некоторых языках вообще все передается по ссылке, в других вообще нет разницы для мелких типов.
    Ответ написан
    Комментировать
  • Как понять что переполняет память в C++?

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

    Потребляет ли много памяти какой-то другой процесс?

    Возможно там утечка каких-то ресурсов, вроде хендлов.

    Каким-нибудь process explorer можно посмотреть сколько хендлов ваша программа имеет, если это число растет, надо разбираться, какие из виндовых объектов вы правильно не уничтожаете. Вроде бы все битмапы вы корректно уничтожаете через DeleteObject, возможно ошибка в другом коде.

    Можно еще поробовать вашу программу подебажить. Вот когда окно вылезает, какой ваш код выполняется? Подключитесь к вашему процессу visual studio и смотрите. Или добавьте отладочный вывод, чтобы понять, какая функция начинает выполнятся но не заканчивает. Это подскажет вам, какие объекты вы не удалили правильно.
    Ответ написан
  • Как исправить некорректное отображение кириллицы?

    Проблема в том, что твоя программа выводит текст в кодировке utf-8, так как файл с кодом имеет такую кодировку, а в консоли на Винде по-умолчанию используются восьмибитные кодовые страницы (для русского языка - это cp866 и cp1251). vscode не виноват.

    Решений несколько:
    1. Поменять кодировку файла
    2. Хранить текст для вывода в консоль в нужной кодировке
    3. Конвертировать текст в нужную кодировку перед выводом в консоль
    4. Поменять кодировку в консоли при помощи chcp на ту, которую использует программа.
    5. Поменять кодировку консоли изнутри программы при помощи setlocale или SetConsoleOutputCP, SetConsoleCP

    С моей точки зрения, самым правильным вариантом будет последний.
    Просто добавь в самое начало main вот такую строку:
    std::setlocale(LC_ALL, "ru_RU.UTF-8");
    И ещё добавь include:
    #include <locale>
    Но обрати внимание, чтобы кодировка файлов оставалась utf-8. Если ты такую строку добавишь в случае, когда у тебя код имеет кодировку 1251 - при выводе снова будут кракозябры.
    Ответ написан
    3 комментария
  • Как анализировать рынок IT, чтобы помочь ребенку с выбором направления?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    В этом возрасте направление надо выбирать интересное, а не востребованное, и быть готовым к тому, что интерес может меняться каждые несколько месяцев.
    Ответ написан
    3 комментария
  • Как анализировать рынок IT, чтобы помочь ребенку с выбором направления?

    Adamos
    @Adamos
    Есть тенденция, которая существует давно и никуда не денется.
    Требуются - программисты, которые не ждут команды и разжеванных заданий, а могут сами начать и кончить.
    Не мечутся в поисках волшебного направления-языка-фреймворка, за который кто-то сразу будет люто платить, а делают проекты на том, что попалось под руку. От начала до конца.
    Внезапно, этот опыт позволяет потом без проблем сменить фреймворк, язык и даже направление.
    Если научишься - работать. А не скакать по верхушкам, хватаясь за интересное и бросая его сразу же, как оказывается, что для углубления в предмет нужно недельку побиться лбом об стену.
    Ответ написан
    Комментировать
  • Как из /128 адреса ipv6 самому себе присвоить /64 или даже /48?

    b1ora
    @b1ora
    настройка-микротик.рф
    /128 меньше, чем /64, ответ никак, получай как минимум /56 чтобы сделать 16 блоков по /64
    Ответ написан
    4 комментария
  • Стоит ли бежать со стартапа?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    В карьерных решениях более продуктивно уходить не от чего-то, а к чему-то. Можете найти работу с условиями лучше - уходите. Не можете - не уходите.
    Ответ написан
    Комментировать
  • Как лучше реализовать ФС - фото- и видеохранилище?

    anthtml
    @anthtml
    Системный администратор программист радиолюбитель
    1. Предпочтительней - проще работать из виртуалки сразу с хранилищем
    2. Если планируется на луне хранить не только эту виртуалку
    А что мешает миграции в первом варианте? Виртуалка переедет на другой хост вместе со старым таргетом и оттуда также к нему приконнектится, если нужно перенести (увеличить) таргет - то просто его перемонтировать к линю.
    Ответ написан
    1 комментарий
  • Почему я могу изменять состояние объекта хранящийся в const std::unique_ptr и const std::shared_ptr?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно сделать указатель на const. Вот этот ваш const, он относится к самому указателю, его нельзя менять (в смысле, на другой адрес). Но после разыменовывания получается не константная ссылка. Вот оно в документации:
    typename std::add_lvalue_reference<T>::type operator*() const


    Там нет никакого const в типе возвращаемого значения, несмотря на то, что оператор можно вызывать у константных экземпляров класса. Зачем конкретно так сделано, я не знаю. Наверно, тут копируется поведение обычных указателей: там тоже можно иметь неизменный указатель на изменяемую область памяти.

    Так что если вы хотите запретить менять объект, то можно сделать так:
    void foo(const std::unique_ptr<const int>& ptr) {
        if (ptr) {
            *ptr += 5; // Ошибка компиляции.
            std::cout << *ptr;
        }
    }
    
    int main() {
        std::unique_ptr<const int> ptr = std::make_unique<const int>(5);
        foo(ptr);
    }


    Правда, придется писать много лишнего кода, если будете передавать неконстантный объект внутрь функции, которая хочет ссылку на константный.

    Но вообще, обычно нет смысла передавать unique_ptr по ссылке. Можно передать по ссылке сам объект, все равно владение в функцию не передается же. И уже там можно навешивать const, если надо. Или, если передавать просто unique_ptr, без ссылки, то даже лишнего кода не надо для обработки const:
    void foo(const std::unique_ptr<const int> ptr) {
    }
    
    int main() {
        std::unique_ptr<int> ptr = std::make_unique<int>(5);
        foo(std::move(ptr));
    }
    Ответ написан
    3 комментария
  • Можно ли использовать не парные Acquire/Release порядки памяти?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    могу ли я использовать Relaxed в 3?

    Если тебе не важно то, что ты при этом можешь пропустить изменение head, то можешь. Но тебе должно быть важно, потому что это же единственная загрузка head в producer_maybe_push().
    Ответ написан
    7 комментариев
  • Как ждать в диапазоне атомарных чисел?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    То, что вы описали в комментариях, это буквально блокировка чтения-записи. Функтор читает данные и может выполнятся параллельно несколько раз, но запись может быть только одна и она блокирует все чтения. Решение описано в википедии: 2 мьютекса, один счетчик. Атомиков не надо.
    Ответ написан
    Комментировать