Задать вопрос
  • Как можно (через Qt или WinAPI) узнать направление ClearType: RGB/BGR/другое?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    https://docs.microsoft.com/en-us/windows/win32/api...
    В Qt нет, посмотрел исходники — либо часть Chromium, либо не выглядывает наружу.
    Ответ написан
    Комментировать
  • Что такое точка доступа Wi-fi?

    @Mercury13
    Программист на «си с крестами» и не только
    Вайфай — локальная сеть.
    Точка доступа — мост (устройство 2-го уровня) между вайфаем и какой-то другой сетью — локальной или провайдерской. (То, что провайдер позволит подключиться по 2-му уровню только одному, реже двум — это другой вопрос.)
    Но точка доступа часто является маршрутизатором, устройством 3-го уровня.
    Ответ написан
    Комментировать
  • Я придумал новый гениальный способ оптимизации игр?

    @Mercury13
    Программист на «си с крестами» и не только
    Гений постольку, поскольку каким-то раком научил движок делать то, чего он не может из коробки. Но есть вопросы.
    Поскольку игра изометрическая, низшие уровни детализации неактуальны. А в обычном 3D — более чем.
    Изометрия обычно не настолько детальна, чтобы загрузка была нужна особенно часто — нужно что-то вроде «при приближении к подуровню грузить его».
    Если движок не поддерживает фоновую подгрузку — всё будет с ней в порядке, не будет игрок испытывать тормозов?
    С мультиплеером всё в порядке?
    Ответ написан
    Комментировать
  • Как вызвать CreateThread внутри Form?

    @Mercury13
    Программист на «си с крестами» и не только
    Tony сказал правильно, но есть ещё одна вещь.
    CreateThread использовать ЗАПРЕЩАЕТСЯ. Точнее, можно — но для этого нужно знать, что делаешь. А так для прикладного прогера правило — надо перевести библиотеку времени выполнения в многопоточный режим, и для этого вызвать аналог из этой самой библиотеки. В Си++ для этого используется функция beginthreadex(), в Delphi — BeginThread.
    Ответ написан
    Комментировать
  • Стоит ли плагину доверят писать unit-тесты?

    @Mercury13
    Программист на «си с крестами» и не только
    Проверим один тест.
    // Какую концепцию проверяем?
       // Это не просто проверка функции ListAll, это проверка какой-то концепции кода
       // Варианты.
       // 1. Пустой listAll() даёт пустой список.
       // 2. Непустой listAll() даёт непустой список.
        void testListAll() {
            ArrayList<Product> productList = new ArrayList<Product>();
            // Проводим поиск в списке — что в этот список вносится?
            // И не будет ли физической зависимости тестов друг от друга?
            // И для чего вообще нужен этот search, если мы listAll тестируем?
            // Что такое ProductRepository и он вообще проверен?
            when(this.productRepository.search((String) any())).thenReturn(productList);
            // Ну, хорошо.
            List<Product> actualListAllResult = this.productService.listAll("Keyword");
            // Отказ, они не same: первый мы только что создали, а второй откуда-то пришёл.
            assertSame(productList, actualListAllResult);
            // Получается, что концепция — поиск, когда ничего не находится?
            assertTrue(actualListAllResult.isEmpty());
            verify(this.productRepository).search((String) any());
            // Получается, единственная концепция, которую мы тестируем,— поиск в пустом списке даёт пустоту
            // (и та некорректная из-за assertSame).
            assertTrue(this.productService.getAll().isEmpty());
        }


    Ну что, понятно, что или фтопку такие инструменты, или нужно их серьёзно осваивать, прежде чем будут приносить хоть какие-то результаты?
    Ответ написан
    Комментировать
  • Как лучше всего использовать ресурс батареи?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Прописать переход на зарядку процентах на 80…90 (обычно ≈95).
    2. Хоть иногда давать разряд-заряд.
    Вот и всё, что мы можем сделать.
    Ответ написан
    Комментировать
  • Как разбить числа по группам так, чтобы в группах находились близкие по значению числа?

    @Mercury13
    Программист на «си с крестами» и не только
    Это называется кластеризация, и самый ходовой метод для неё — K-means.
    Ответ написан
    2 комментария
  • Можно ли сделать код, который, если constexpr-выражение true, выдаст предупреждение?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Придумал.

    [[maybe_unused]] byte debugWarning = SIMULATE_CHANGED_HORIZON * 1000;


    В случае false компиляция пройдёт гладко. В случае true преобразование 1000 → byte выдаст предупреждение.
    Ответ написан
    Комментировать
  • Код не проходит проверку по времени, как ускорить?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужно использовать тип данных «словарь» (в Си++ std::map/unordered_map), а не прямой поиск.
    Если в Питоне, как в PHP, массивы могут иметь любой индекс (ну не знаю я, не знаю) — вот вам и словарь.
    Ответ написан
    Комментировать
  • Почему char - 1 байт, а символьный литерал ('A') - 4?

    @Mercury13
    Программист на «си с крестами» и не только
    А теперь скажу правильный ответ.
    В Си символьный литерал имеет тип int и потому его sizeof 4 байта.
    В Си++ у него тип char и 1 байт. Потому те, кто создавал CPP-файл, проблемы не видели. Очевидно, связано с перегрузкой функций: как-то не хочется, чтобы в foo('A') вызывалась версия для int.
    #include <stdio.h>
    
    int main()
    {
        int sz = sizeof('A');  // латинское
        printf("sz = %d\n", sz);
        return 0;
    }

    Си: 4
    Си++: 1

    При написании char test='A' на стеке будет 1 байт (+выравнивание). Здесь Си, грубо говоря, проводит преобразование типа — прямо при компиляции. Если написать char test=L'Й', сообщит, что преобразование при компиляции ushort→char обрежет результат с 1049 до 25.
    Ответ написан
    Комментировать
  • Сложность алгоритмов для определения подстроки в строке?

    @Mercury13
    Программист на «си с крестами» и не только
    H = |haystack|, n = |needle|, a — размер алфавита.
    Примитивный алгоритм: предобработки нет, работа в среднем 2H, максимум O(Hn).
    Типичные быстрые алгоритмы: предобработка O(n) или O(n+a), работа в среднем <H, максимум O(Hn).
    Автоматные алгоритмы: предобработка O(na) или O(n+a), работа =H.
    Существуют СТРАШНЫЕ алгоритмы с работой в среднем <H и максимум O(H), где применяются — не знаю.
    Если нужно проводить несколько поисков одной «иголки» в разных «стогах», нужна всего одна предобработка.
    Ответ написан
    Комментировать
  • Как работает Hmac?

    @Mercury13
    Программист на «си с крестами» и не только
    HMAC — это так называемая имитовставка.
    То есть нечто среднее между хэш-функцией и электронной подписью.
    Тот, кто изменил сообщение и не знает ключа, НЕ МОЖЕТ подделать имитовставку — в отличие от хэш-функции.
    Но ключ подписи и проверки ОДИН И ТОТ ЖЕ — в отличие от электронной подписи.

    В современных веб-службах имитовставка используется для одного из вариантов аутентификации: сообщения закрыты прочным транспортным протоколом, но нет возможности проверить, тот ли человек на другом конце провода. Для этого подписываем всё тело запроса, и сервер, владеющий тем же ключом, сможет убедиться, что запрос сформирован нужным человеком.
    Ответ написан
    7 комментариев
  • Какие есть в Qt способы синхронизировать кусок кода с интерфейсным потоком?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    К сожалению, только сигналы — и ключевое слово BlockingQueuedConnection.
    А всё остальное — это как сделать синхроблок рядом с процедурой, а сигнал-слот — где-нибудь в главном окне. Скажем, так.

    class AsyncSimpleContext {  // интерфейс
    public:
      virtual void syncExec(const Runnable& body) = 0;
      template <class Body>
      void syncExecT(const Body& body); // тело упущу, тут всё стандартно,
                                             // идиома «виртуальный шаблон»
    }
    
    class FmMain : public AsyncSimpleContext
    {
      // Разрешите не писать реализацию syncExec — тут всё просто:
      // в конструкторе соединить сигнал со слотом методом BlockingQueuedConnection
      // в syncExec проверить id потока и или вызвать прямо, или возбудить сигнал.
    signals:
       void sigSyncExec(const Runnable&);
    private slots:
       void slotSyncExec(const Runnable&);
    }


    …и передавая куда-нибудь как-нибудь интерфейс AsyncSimpleContext, мы можем синхронизировать что-то с интерфейсом.
    Ответ написан
    Комментировать
  • Что значит после класса?

    @Mercury13
    Программист на «си с крестами» и не только
    Шаблонный класс.
    Гугли «Java Generics»

    String — Input parameter type
    Integer — progress report type
    String — result parameter type
    Ответ написан
    Комментировать
  • Как запустить код Си в проекте С++?

    @Mercury13
    Программист на «си с крестами» и не только
    не удается преобразовать 'char*' в 'int*' для аргумента '1' в 'int

    Как правило, ошибка. Функция хотела указатель на 4-байтовые слова — а мы передаём ей указатель на байты.
    Если очень нужно рассматривать int* как char* (например, работаем не с данными какого-то определённого типа, а просто с байтами в памяти) — используйте reinterpret_cast.

    недопустимое преобразование из 'int*' в 'int'

    Почти всегда ошибка. Функция хотела число — а мы ей передаём ей указатель.
    Если реально по какой-то причине нужно значение указателя воспринимать как число — используйте reinterpret_cast.

    Возможен и другой вариант — вы просто упустили операцию «разыменовать» *.

    warning: narrowing conversion of '143' from 'int' to 'char' inside

    Точно ошибка — 143 не вписывается в char (−128…127). Если очень надо, используй static_cast.

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

    @Mercury13
    Программист на «си с крестами» и не только
    XnView — там в диалоге «Batch processing» есть add text и watermark.
    Ответ написан
    Комментировать
  • Зачем делают разные сайты для мобильной и десктопной версии веб-приложений?

    @Mercury13
    Программист на «си с крестами» и не только
    Сайт может быть:
    • преимущественно настольный (Посмотре.ли);
    • преимущественно мобильный (Эгея. Или вот знакомая пишет внутреннюю систему учёта отпускных — всё сделано, чтобы работало с мобилы);
    • адаптивный (Розетка — простите, я с Украины. Ну и Хабр Q&A);
    • с сильно разными шкурками под настольный и мобильный (Википедия, YouTube)

    Какие факторы на это влияют:
    • Умение веб-программиста — что он умеет, то и пишет.
    • Используемый инструментарий — скажем, у нас есть древний сайт, надо переписать под мобилу.
    • Соотношение «настольный/мобильный» — например, заказ пиццы обязательно делать преимущественно мобильным или адаптивным.
    • Контент — если много картинок, приходится думать. И наоборот, простой блог без проблем можно сделать преимущественно мобильным, что и сделал Бирман в своей Эгее.
    • Особый настольный инструментарий — например, вики смотрят и с мобилы, но редактирование с мобилы — крайне редкий сценарий и обычно ограничивается редактурой. YouTube с мобилы много глазеют, но залить с мобилы — дело значительно более редкое. И уж совсем редкое — управлять видеоблогом с мобилы.

    Кодовая база общая, разные только шкурки.
    Ответ написан
    Комментировать
  • Как работают интерпретаторы компилирующего типа?

    @Mercury13
    Программист на «си с крестами» и не только
    1) То есть считал строку, скомпилировал - получил двоичный код. Выполнил этот двоичный код.

    НЕТ. Считал — выполнил. Выполняется машинный код интерпретатора, а не программы.

    3) Байт-код понятен среде/виртуальной машине (.NET, Java), которая компилирует байт-код в двоичный код

    В ЧИСТОМ СЛУЧАЕ — НЕТ. Считал команду байт-кода — выполнил. Точно так же выполняется машинный код интерпретатора, а не программы. Что-то вроде:
    switch (opcode) {
    case OP_ADD: {
           auto res = stack.pop() + stack.pop();
           stack.push(res);
       }
    .....
    }


    Байт-код используется по нескольким причинам.
    1. 3 быстрее 1.
    2. С расширением языка мы меняем только компиляцию в байт-код. Оптимизация байт-кода, интерпретатор — остаются.

    А компиляция в машинный код в 1 и 3 — это так называемая JIT-компиляция. Она может выполняться не всегда. Одни команды могут быть в машинном коде, а другие — интерпретироваться.

    Кроме того, байт-код часто используется и в классических компиляторах 2-го типа! Это позволяет делать многоплатформенные коллекции компиляторов — все frontend’ы компилируют в байт-код, затем с байт-кодом делаем какую-то магию вроде оптимизации, отдаём его backend’у, и тот готовит OBJ-файл для нужного процессора.
    Ответ написан
    Комментировать
  • Почему нельзя возвращать объект по значению в non-const &?

    @Mercury13
    Программист на «си с крестами» и не только
    const struct s & ref = f();
    Этот механизм называется «продление жизни временного объекта».
    Можно написать вот так.
    struct s && ref = f();

    Главная причина преобразования временного объекта только в const T& и T&& — тонкие ошибки при суперпозиции функций.
    А именно — временный объект мы ни в коем случае не должны передать в функцию, принимающую s&.
    void modify(s& arg) { ++arg[1]; }
    
    ...
    
    modify(f());

    Мы вызвали функцию f(), её результат передали в modify, и… похѣрили.
    Ответ написан
    Комментировать
  • Для чего нужны спецификаторы в C?

    @Mercury13
    Программист на «си с крестами» и не только
    Связано это в первую очередь с механизмом передачи переменных аргументов в функцию Си.
    Они просто сваливаются в стеке один за другим — и нужно каким-то образом показать, сколько этих аргументов и каких типов. И уж во вторую очередь — формат вывода: точность, система счисления, заглавные буквы, ширина и прочее.

    Именно по этой причине — спецификаторы printf в первую очередь задают типы аргументов — функция printf ничего не может сделать, если мы ошиблись с типом. Потому что %d (%ld, %lld) для неё в первую очередь способ понять, сколько байтов взять со стека и как их интерпретировать.

    Си++ для этих целей использует перегрузку функций, Delphi — тэгированные данные, Java — объектный полиморфизм. Так что они знают, с каким типом данных имеют дело — и для них не нужно различать signed/unsigned int/long/long long. Для них %d/%x/%X означает разные варианты целого, %e/f/g — разные варианты дробного, и. т.д. Если для дробного пользователь напишет %d, они или выкинут ошибку, или как-то интерпретируют.
    Ответ написан
    Комментировать