Задать вопрос
  • Как пакетно отредактировать множество фотографий?

    @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, они или выкинут ошибку, или как-то интерпретируют.
    Ответ написан
    Комментировать
  • Можно ли спикером микротика сгенерировать голос?

    @Mercury13
    Программист на «си с крестами» и не только
    На многозадачных ОС — скорее всего, нет. Потому что в DOS мы могли напрямую управлять мембраной динамика, а для этого нужно жёсткое реальное время. Чтобы несколько тысяч раз в секунду по расписанию управление передавалось нашей программе. Кстати, под Windows все эти программы превращались в рёв реактивного двигателя, помните?

    А музыкой занимается программируемый таймер, железная микросхема. Чтобы звук был побогаче, там обычно налаживают быстрые арпеджио, единицы-десятки раз в секунду — быстродействия многозадачной ОС общего назначения вполне хватает.

    Звуковая плата управляет динамиком своими силами, через DMA, без участия процессора.
    Ответ написан
  • Возможно ли автоматическое добавление переменной компилятором в namespace?

    @Mercury13
    Программист на «си с крестами» и не только
    В любом языке можно только так.
    namespace Addresses {
      uintptr_t myAddresses = processManager.xxx;
    }

    Только в CPP-файле; в хедере надо
    namespace Addresses {
      extern uintptr_t myAddresses;
    }

    Но не советую по двум причинам.
    1. Контроль задержек при инициализации программы — дело противное. На всех языках. Например, на Java ME я просил: все длинные операции делать, когда на экране что-то появится.
    2. Вторая причина специфичная для Си++. Порядок инициализации разных модулей не определён. Если менеджер в одном модуле, а адреса в другом, адреса могут с вероятностью 50/50 инициализироваться, когда менеджера ещё нет.
    Ответ написан
    6 комментариев
  • Как найти слово, гарантированно отсутствующее в наборе?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Придумал, причём тупо. Комбинаторикой высчитываем, какой длины (по принципу Дирихле) должно быть наше слово: например, если у нас цифры от 0 до 9 и 125 строк, достаточно взять трёхзначные. Вот мы берём 126 битов (ну или 128 для круглого счёта), из наших чисел берём только трёхзначные и начинаем заполнять биты. Есть, например, 025 — вот в 25-й бит и суём единичку. После этого остаётся найти в битовой маске ноль и преобразовать в нашу строку: на 45-м месте — значит, 045.
    Ответ написан
    Комментировать
  • Как заменить одинарный обратный слеш?

    @Mercury13
    Программист на «си с крестами» и не только
    Не сильно оптимизированный, но действующий код.
    CONST_STR = string_view или const string& в зависимости от версии Си.
    На выходе — кол-во замен.
    size_t str::replace(
            std::string& aString,
            const char aWhat,
            const char aByWhat)
    {
        size_t r = 0;
        FOR_S(i, 0, aString.length())
            if (aString[i] == aWhat) {
                aString[i] = aByWhat;
                ++r;
            }
        return r;
    }
    
    size_t str::replace(
            std::string &aString,
            char aWhat,
            CONST_STR aByWhat)
    {
        if (aByWhat.length()==1)
        {   // Simple replace
            return str::replace(aString, aWhat, aByWhat[0]);
        }
        // More complex replace
        static const size_t szWhat = 1;
        const size_t szByWhat = aByWhat.length();
        size_t p = 0, r = 0;
        while ((p = aString.find(aWhat, p)) != std::string::npos)
        {
            aString.replace(p, szWhat, aByWhat);
            p += szByWhat;
            ++r;
        }
        return r;
    }
    Ответ написан
    Комментировать
  • Как в Qt (например, QTextBrowser) сделать подчёркивание тоньше пикселя?

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

    Хорошего способа нет, но самая близкая разглючка — через градиентный фон. Например.
    style = " style='color:" CNAME_LINK_POPUP "; "
                         "text-decoration:none; "
                         "background:qlineargradient(x1:0, y1:1, x2:0, y2:0, "
                                "stop:0 " CNAME_LINK_POPUP ", stop:0.06 #00000000, stop:1 #00000000);'";
    Ответ написан
    Комментировать
  • Где хранится nullptr? Для разных программ она разная?

    @Mercury13
    Программист на «си с крестами» и не только
    Что значит «хранится»?
    • Значение nullptr хранится в переменной-указателе — как и любое &someObject.
    • Объекта правильной «объектной» формы (если, конечно, у объекта присутствует какой-то инвариант или хотя бы таблица виртуальных методов) по адресу *nullptr нет; в большинстве ОС разыменование nullptr приводит к нарушению сегментации и мгновенному вылету (но не обязательно — например, DOS).
    • Во всех известных мне ABI (x86/DOS, x86 и x64/Windows, x86 и x64/Linux) nullptr равен нулевому адресу. Это обосновано — по этому адресу обычно располагается таблица прерываний, точка входа, префиксный сегмент или прочая системная хрѣнь, сюда точно соваться не стоит. Но теоретически не обязательно. Этот адрес, естественно, общий для ABI, чтобы можно было объединять в одну программу результаты компиляции разными языками.
    Ответ написан
    Комментировать
  • Возможно ли сделать шаблонную функцию дружественной классу?

    @Mercury13
    Программист на «си с крестами» и не только
    #include <iostream>
    
    class Wrap
    {
    public:
        Wrap(int x) : value(x) {}
    private:
        int value;
    
        template <class T>
        friend void out(const T&);
    };
    
    template <>
    void out(const Wrap& x)
        { std::cout << x.value << std::endl; }
    
    int main()
    {
        Wrap x(42);
        out(x);
        return 0;
    }


    Если нужно в пространстве имён…
    spoiler
    #include <iostream>
    
    namespace qq {
        template <class T>
        void out(const T&);
    }
    
    class Wrap
    {
    public:
        Wrap(int x) : value(x) {}
    private:
        int value;
    
        template <class T>
        friend void qq::out(const T&);
    };
    
    template <>
    void qq::out(const Wrap& x)
        { std::cout << x.value << std::endl; }
    
    int main()
    {
        Wrap x(42);
        qq::out(x);
        return 0;
    }
    Ответ написан
    Комментировать
  • Как решить ошибку "String is not null terminated"?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы неправильно пользуетесь функцией strcat_s.
    Традиционно в Си (видимо, из-за особенностей машины PDP-11) каждая строчка заканчивается нулевым символом.
    Смысл strcat_s — если строка находится в буфере ограниченной длины и по какой-то причине не нуль-терминированная, функция не полезет в «левую» память, а ограничится размером буфера. Вторым параметром должна быть длина буфера, а не strlen, который обесценивает весь смысл суффикса «safe».
    Ответ написан
    Комментировать
  • Как поделить на о в С++?

    @Mercury13
    Программист на «си с крестами» и не только
    Деление на целочисленный 0 невозможно, происходит авария «деление на 0».

    В процессорах, которые делят 2w:w → w, эта авария происходит и в других случаях. Скажем, если слово — это две десятичных цифры, то 1000:2 даст ошибку: 500 не укладывается в эти две цифры. В Си++, который умеет делить только w/w, такое сделать можно только на ассемблере.

    Деление конечного на дробный 0.0 даёт ±∞ — особое «число», которое больше/меньше любого конечного.
    Деление 0.0/0.0 даёт NaN (not a number, не-число).

    Откуда вы взяли мантиссу 1,87235 — я не знаю. Минимальное денормализованное число в float 1.4e−45, в double 4.9e−324. Почему так мало знаков — да потому что погрешность у таких чисел ±100%: меньше только 0, а следующее вдвое больше.

    UPD. В редко используемом и очень медленном extended (= long double) есть что-то похожее — 1.9e−4951.
    Ответ написан
    Комментировать
  • Как правильно оценить сложность алгоритма O(n)?

    @Mercury13
    Программист на «си с крестами» и не только
    f(x) = O(g(x)) при x→y — это так называемый символ Ландау.
    И означает, что при x, достаточно близких к y, f(x)<k·g(x). Так что 2x или 1000x — извините, не важно.

    Отсюда же запись O(log n) — ведь разные логарифмы отличаются на константу, которую символы Ландау съедают.

    Чем символы Ландау интересны программистам?
    1. Кэшами, быстрым процессором, «хитрым» программированием и прочим на больших наборах данных можно выиграть, например, в разы. Порядком сложности алгоритма — намного, намного больше.
    2. Пока закон Мура действовал, объёмы данных росли экспоненциально — так что быстро доходило до того, что программу начинали использовать на наборах данных, для которых она просто не предназначалась.
    3. Практически приемлемые алгоритмы обычно имеют небольшую сложность — например, до O(n³). И, например, линейный алгоритм за приемлемое время обработает миллионы элементов, n log n — сотни тысяч, n² — тысячи, n³ — сотни.
    4. Программисты отлаживают на небольших наборах данных, которые можно обработать вручную. Так что разница между отладочными и боевыми данными бывает большая — а значит, порядок сложности должен влиять сильнее, чем остальные факторы.
    Ответ написан
    1 комментарий
  • Как уменьшить выходной exe при компиляции?

    @Mercury13
    Программист на «си с крестами» и не только
    Это вообще как компилируете?
    Если у вас MinGW и консольная программа, советую что-то вроде
    -O3 -Os -static-libgcc -static-libstdc++ -static -lpthread

    Получается самодостаточный EXE’шник, и для небольших программ ≈400K, для программ побольше — около 2М.
    Ответ написан
    Комментировать
  • Что за функция swow?

    @Mercury13
    Программист на «си с крестами» и не только
    Это чья-то собственная. Вы её и не найдёте. Особенно вместе с общими названиями generate и foo.
    Шерстите свой исходник. А если он не полный — вы сами себе злобный буратино.
    Ответ написан
    Комментировать
  • Почему финализированные классы в исходниках java имеют private конструкторы?

    @Mercury13
    Программист на «си с крестами» и не только
    Ничем особенным. Просто библиотечные функции сильнее защищают от «нештатного» использования.
    Ответ написан
    Комментировать
  • Как выполнить размещение k элементов из n?

    @Mercury13
    Программист на «си с крестами» и не только
    Будут повторы?
    Если не будет — то достаточно отсортировать char’ы и использовать числовой алгоритм.
    Если будут — ищите «размещения с повторами», и тоже сортируйте.
    Ответ написан
    Комментировать
  • Что обозначают записи: Class object(&anotherObject); и AnotherClass anotherObject(10);?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Создать в стандартном месте (на стеке или в сегменте данных) объект object типа Class с вызовом конструктора Class::Class(AnotherObject*).
    2. Создать там же объект anotherObject типа AnotherClass с вызовом конструктора AnotherClass::AnotherClass(int).
    Ответ написан
    Комментировать