Ответы пользователя по тегу C
  • Можно ли использовать в wasm загрузку dll библиотеки?

    TrueBers
    @TrueBers
    Гуглю за еду
    В WebAssembly изначально изолированная среда для исполнения. Он ничего не знает про DLL и вообще что-то за пределами модулей.
    Браузеры тоже пишутся так, чтобы никакие левые дллки не могли вмешиваться в процесс их работы и делать, что хотят.

    Единственный вариант -- это тяжёлый реверс браузера и инжект дллки и кода в рантайм.
    Ответ написан
    Комментировать
  • Какую книгу прочитать по C?

    TrueBers
    @TrueBers
    Гуглю за еду
    Спецификация Стандарта C18 -- 540 страниц.
    Спецификация Стандарта С++20 -- 1900 страниц.

    Разница есть? :-D
    Ответ написан
    Комментировать
  • ЯП С. Аналог или замена graphics.h для работы через OSX?

    TrueBers
    @TrueBers
    Гуглю за еду
    Используй SDL
    Ответ написан
    Комментировать
  • Как заменить символы в текстовом файле?

    TrueBers
    @TrueBers
    Гуглю за еду
    Подскажите как это лучше всего сделать с использованием только стандартных библиотек C++?

    Если прям true C++ way, то вам нужно использовать std::fstream. Для него нужно реализовать стандартный std::streambuf и во время записи в файл, когда буфер сбрасывается, у std::streambuf вызывается виртуальный метод overflow(), вот его перегружаете, проходите по буферу, делаете нужные вам изменения и сбрасываете буфер дальше на запись. Примерно, как тут.
    Это если важна архитектура, гибкость, переиспользование кода и трушность C++.

    А если более-менее простой вариант, то недо-true C++ way выглядит
    примерно так
    #include <algorithm>
    #include <fstream>
    #include <iostream>
    #include <iterator>
    
    int main() {
    
      std::ofstream out_file( "out.txt" );
      std::ifstream in_file( "in.txt" );
      std::string/*stream*/ some_buffer;
    
      using char_type = decltype(out_file)::char_type;
      using in_iter = std::istream_iterator< char_type >;
    
      if ( !in_file.is_open() || !out_file.is_open() )
        return EXIT_FAILURE;
    
      std::transform(in_iter(in_file), in_iter(), std::ostream_iterator< char_type >(out_file),
                     [&some_buffer] (const char_type &c) {
    
                       if ( !std::isalpha( static_cast<unsigned char>(c) ) || c == '\n' || c == '\r' )
                         return ' ';
    
                       // if шило, then мыло, буферизуем если надо, и т. п.
    
                       return c;
                     });
    
      return EXIT_SUCCESS;
    }
    Ответ написан
    3 комментария
  • Почему в Си допускается переполнение массива?

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

    По сути, Си — это просто высокоуровневый ассемблер. В ассемблере нет понятия ошибок вообще, всё на плечах разработчика. Если ему нужно проверять на переполнение, он сам должен реализовать этот функционал, а не терять на этом производительность, когда ему это не нужно.
    Ответ написан
    Комментировать
  • Поиск слов в векторе c++?

    TrueBers
    @TrueBers
    Гуглю за еду
    Ответ написан
    Комментировать
  • Почему нельзя использовать указатель без объявления переменной?

    TrueBers
    @TrueBers
    Гуглю за еду
    А потому что, учите ассемблер, вот почему.
    Разработчика на C/C++ не бывает без базовых знаний ассемблера.
    Можно взглянуть сюда и понять очень многое.

    На 6-й строке ассемблерного кода у вас происходит выделение стекового фрейма. Это та область памяти, где будут храниться ваши локальные переменные, которые вы объявляете в текущей функции, т. е. в нашем случае это int var; int *pvar;. Несмотря на то, что сумма размеров этих переменных на стеке sizeof(int) + sizeof(int*) = 12 для x86_64, выделяется 16 байт согласно пункту 3.2.2 SystemV ABI AMD64, который говорит, что стековый фрейм должен быть выровнен по границе 16 байт. На другой архитектуре здесь может быть другое правило.

    Стек растёт вниз по адресам, т. е. выделение памяти на нём — это просто вычитание (инструкция SUB) из адреса его вершины (регистр RSP) числа, равного тому количеству памяти, которое мы хотим выделить. К вам как бы «всплывает» кусок памяти «откуда-то снизу». Эта память скорее всего использовалась предыдущими вызовами функций и осталась не затёрта! Соответственно, вы должны инициализировать этот поюзаный кем-то кусок под себя.
    Что-то типа аналогии со школы или универа, когда в аудитории есть такая раздвигающаяся доска из двух или трёх частей, видели наверное, когда выдвигаешь одну часть, а другая задвигается. Так вот, когда вы приходите на лекцию, выдвигаете доску, а там, внезапно, предыдущая группа не стёрла за собой свои творения, и вам придётся это стирать и писать вещи, относящиеся к вашему предмету. Естественно, если вы попытаетесь использовать для вашего предмета то, что осталось от предыдущей группы, получится бред в большинстве случаев.

    Когда адрес вашего указателя где-то используется без инициализации (7-я строка асм кода), он возьмёт тот самый мусор, который к нам пришёл при выделении фрейма.
    Получается лотерея: если этот мусор случайно оказывается действующим указателем на память, доступную для записи, ОС не выбрасывает исключение и пишет куда-то в непонятное место, ломая тем самым случайное место в вашей программе. Т. е. вы попадаете на тот случай, когда во фрейме попался до сих пор действующий указатель из мусора предыдущей функции, которая использовала этот кусок фрейма и не затёрла. А когда лотерея проиграна, и попали не на указатель, а на не пойми что, ОС бросает исключение. Поэтому ошибка не всегда проявляется.

    Это всё частный случай реализации языка Си для конкретной архитектуры. Конечно, в терминах стандарта таких вещей не бывает вообще, а объявлено просто как неопределённое поведение, которого нужно избегать.
    Ответ написан
    1 комментарий
  • С или modernC++ для IoT?

    TrueBers
    @TrueBers
    Гуглю за еду
    Так говорите, как будто С++ это 2 вещи: shared_ptr и исключения :D

    Вы смутно понимаете, похоже, в чём их назначение.

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

    Два. Любые эксепшены, rtti, наследования, диспетчеризация и т. п. в embed'е это дикий оверхед. Но при этом, почему-то многие софтовые компании, включая гугл, просто выключают у себя в проектах поддержку исключений и rtti. И на этом "огрызке" всё работает почему-то. К тому же, размер бинарника для имбеда довольно важен и не на последнем месте. Выпилив исключения и rtti, можно очень хорошо выкинуть мусор.

    shared_ptr — не серебряная пуля. Как уже сказал fshp, они используются в, ну просто, очень ограниченном количестве случаев. Их, как и исключения, нельзя пихать куда попало. Посмотрите выступления Шона Парента, почитайте его пейперы. Очень толковый мужик из Adobe, один из главных инженеров Фотошопа. Он там хорошо описывает и показывает на примерах, что shared_ptr — это просто хорошо замаскированная глобальная переменная, по сути, да ещё и с оверхедом от атомиков. И перед тем, как его использовать, сто раз подумайте, зачем он вам здесь нужен. В 99% случаев, можно обойтись без него, так же как и без RTTI. При этом, unique_ptr — очень удобная и полезная штука.

    Вам современный C++ предлагает множество сишных способов возврата значения вместо эксепшенов. Вы можете возвращать тот же tied tuple, optional, variant, any, error_condition, error_code. Хоть они и сами любят повыбрасывать исключения, но код намного чище и легче отлаживать и понимать, чем миллион вложенных исключений с дикой иерархией и оверхедом.

    А уж за что следует использовать плюсы, так это за мощь алгоритмов, итераторов, трейтов, лямбд, семантики переноса, удобных атомиков там, где они действительно нужны. Ну и, конечно, шаблоны 17-го стандарта могут хоть чёрта лысого в компайл тайме запилить.

    Если вы из всего вышеперечисленного, пользуетесь только shared_ptr и исключениями, то C++ вам не нужен.
    Ответ написан
    1 комментарий
  • Сервер на Си, как и зачем?

    TrueBers
    @TrueBers
    Гуглю за еду
    libuv
    libevent

    Самые шустрые и распространённые библиотеки.
    Первая используется в ядре Node.js.
    Вторая — в куче проектов типа хрома, тора, файрфокса, мускуля. Умеет http-роутер из коробки.

    На Си дурной тон писать сервер, когда не знаешь Си. Бред наркомана.
    90% всех существующих серверов написано на Си. Другое дело, что надо знать одновременно и язык, и тонкости ОС, и тонкости сетей, уметь пользоваться профилировщиками памяти. Ну, и времени нужно очень приличное количество.
    Ответ написан
    Комментировать
  • Как перевести на си в HEX код(bmp)?

    TrueBers
    @TrueBers
    Гуглю за еду
    Ответ написан
    Комментировать
  • Где и как хранится имя переменной?

    TrueBers
    @TrueBers
    Гуглю за еду
    Имена переменных пишутся для человека-разработчика для удобства чтения и восприятия. Железке-процессору нужен только адрес этой переменной, имя ему ни к чему.
    Ответ написан
    Комментировать
  • Почему gluLookAt не меняет положение камеры?

    TrueBers
    @TrueBers
    Гуглю за еду
    Потому что хватит учить технологии 1999 года!
    Учите современный OpenGL, с конвеером, нормальным батчингом, шейдерами и прочими плюшками.

    В том, что вы учите нет никакого смысла, в современных версиях это уже всё удалено из стандарта и не поддерживается. Придётся заново переучиваться потом, если вы, конечно, не желаете писать игры под NVidia MX440, советую как можно раньше начать учить хотя бы OpenGL 3.3, пока не поздно.
    Ответ написан
  • Как выключить ПК средствами Си?

    TrueBers
    @TrueBers
    Гуглю за еду
    Так вы не находите код с бездумным копированием его в исходники, а разберитесь как он работает, какие бывают интерфейсы для управления питанием. Убедитесь, какие интерфейсы поддерживает ваша система, биос.

    Гуглите APM power off, либо ACPI global state G2 (или sleep state S5).

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

    А у вас какой-то кусок из APM, выдранный непонятно откуда. Почему он по-вашему должен заработать?

    Откройте исходники любой современной ОС, и посмотрите, как там сделано. Там всё порядком посложнее, чем просто 5 команд.
    Ответ написан
    1 комментарий
  • Как UTF-8 помещается в char?

    TrueBers
    @TrueBers
    Гуглю за еду
    А никак не помещается.
    Потому что Си не поддерживает обработку строк в UTF-8. Для этого нужны сторонние библиотеки, которые умеют делать нормализацию, считать длину строки в абстрактных символах, а не кодпоинтах, и т. д. Поддержки этого всего у Си и C++ из коробки нет.
    Ну, вы можете, конечно, запихнуть UTF-8 поток в массив char'ов, но ни одна нативная функция для работы со строками не будет с ним работать правильно. Даже длину строки никогда не сможет посчитать.

    Поэтому, ответ прост: в C/C++ для работы с UTF8 используйте стороннюю библиотеку.
    И да, никогда не используйте wchar_t нигде, где не можете этого избежать, например, в апи сторонних библиотек. wchar_t это тупо костыль в дизайне языка, который признали даже создатели этих языков.
    Ответ написан
  • Как в Visual Studio Code сразу компилировать код Си?

    TrueBers
    @TrueBers
    Гуглю за еду
    Установить компилятор и плагин для C/C++.
    Ответ написан
    1 комментарий