Задать вопрос
Ответы пользователя по тегу C
  • Как передать двумерный массив функции?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как передать двумерный массив функции?

    https://qna.habr.com/answer?answer_id=513953#answe...
    Ответ написан
    Комментировать
  • Какие есть специфичные функции для glibc?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    с чем могут возникнуть проблемы

    Можно начать отсюда.
    Из моего опыта, самое часто всплывающее отличие glibc от других libc -- поддержка версионирования символов.
    Ответ написан
  • Как загрузить ядро тиа ELF через службы UEFI (gnu-efi)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Я пытаюсь загрузить 64-битное ядро по адресу 0x1000

    Я вижу в этом коде три проблемы:
    1. AllocatePages только возвращает адрес выделенной памяти по адресу в последнем параметре. Т.е. куда будут загружены сегменты ELF сказать нельзя и, соответственно, без динамической релокации этот ELF скорее всего работать не будет.
    2. Нет гарантии, что между блоками памяти выделенными через AllocatePages будет то же расстояние, что и между сегментами ELF, в то время как кодогенерация с флагом -fPIE вполне может считать это расснояние неизменным. Такой ELF нужно загружать в один большой блок памяти, сохраняя расстояние между сегментами.
    3. В следствие пункта 1 запуск ядра по адресу header.e_entry -- это прыжок в неизвестность.
    Ответ написан
    Комментировать
  • Как написать Netflow сенсор с нуля?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как мне модифицировать мою программу, чтобы она могла определять потоки и корректно отправлять их коллектору?

    Для этого тебе надо понять, что такое "потоки" о которых ты говоришь, где находится информация о принадлежности пакета потоку и как до неё добираться.

    Если ограничиться определением по ссылке, то тебе надо будет разбирать сырые пакеты до сетевого уровня, откидывать не-IP, из IP извлекать IP-протокол, адрес источника, адрес назначения и тип сервиса, для протоколов TCP и UDP дополнительно извлекать порт источника и порт назначения. Всё это довольно просто сделать самому вооружившись RFC по упомянутым протоколам. Также надо будет понять, что делать с фрагментированными IP-пакетами.
    Ответ написан
    Комментировать
  • Зачем нужен signed в Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    по умолчанию int является signed

    А вот о char этого сказать нельзя, знаковость char зависит от реализации. Вдобавок, в стандарте есть следующая сноска (https://www.open-std.org/JTC1/SC22/WG14/www/docs/n... 6.2.5:15):
    Irrespective of the choice made, char is a separate type from the 
    other two and is not compatible with either.


    signed char -- это, пожалуй, единственное не вызывающее вопросов применение ключевого слова signed в C-коде написанном человеком. В остальных случаях роль signed -- чисто декоративная.
    Ответ написан
    Комментировать
  • Как сделать, чтобы printf() заменял -nan на любой заданный символ?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как сделать, чтобы вместо -nan печатался символ "-" ?

    Только добавив свою логику в свою программу, проверяющую значение на NaN и печатающую в зависимости от этого то или иное значение. С помощью стандартного printf -- никак.
    Ответ написан
    Комментировать
  • Указатели в языке Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему программа завершилась? Вмешалась ОС? Но если так, то почему?

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

    Почему я не могу поменять значение самого указателя (ведь указатель - это всего лишь ссылка на адрес памяти, а не на значение).

    Значение указателя ты поменять можешь, но это не то, что было написано в коде. В коде было написано поменять значение на которое указатель указывает. Поменять указатель было бы a = (int *)10;

    могу ли я указателю дать ссылку на конкретную ячейку в памяти?

    Можешь, но под ОС с виртуальной памятью это в большинстве случаев не имеет смысла. API в таких ОС обычно устроены так, что ты просишь выделить область памяти с заданными характеристиками, а ОС выполняет выделение и возвращает тебе адрес выделенного участка.

    получаю ошибку, ведь вряд ли адрес памяти у указателя хранится в виде 16-ричного целочисленного литерала.

    В памяти всё хранится как последовательность байтов. Любую последовательность байтов можно проинтерпретировать как указатель. Но чтобы компилятор С понял что ты имеешь в виду, ему надо явно сказать, что ты хочешь проинтерпретировать целое число как адрес: int *a = (int *)0x0061FF18;
    Ответ написан
    Комментировать
  • Почему inline функция не компилилируется?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему так происходит?

    Потому что стандарт С11 (9899:201x 6.7.4:7, черновик доступен тут) говорит следующее про спецификатор inline:

    Any function with internal linkage can be an inline function. For a function
    with external linkage, the following restrictions apply: If a function is declared
    with an inline function specifier, then it shall also be defined in the same translation
    unit. If all of the file scope declarations for a function in a translation unit include
    the inline function specifier without extern, then the definition in that translation
    unit is an inline definition. An inline definition does not provide an external
    definition for the function, and does not forbid an external definition in another
    translation unit. An inline definition provides an alternative to an external
    definition, which a translator may use to implement any call to the function
    in the same translation unit. It is unspecified whether a call to the function uses
    the inline definition or the external definition.

    Самое главное тут -- в середине: инлайн-реализация не предоставляет и не запрещает реализацию со внешней линковкой, и в последнем предложении: транслятор волен сам выбирать, какую реализацию функции использовать -- инлайновую или со внешней линковкой.
    Поскольку ты написал так:
    inline void some_inline_func(uint32_t num)
    {
        . . .
    }

    ты тем самым реализовал инлайн-версию этой функции, но не реализовал версию со внешней линковкой. А транслятор выбрал (вернее ты ему подсказал выбрать, опцией -O0) использовать реализацию функции со внешней линковкой, поэтому ты получил ошибку от линковщика.

    Вариантов решения этой проблемы примерно 3:
    - определить функцию следующим образом:
    extern inline void some_inline_func(uint32_t num)
    {
        . . .
    }

    Такая функция будет доступна из других единиц трансляции.

    - либо определить функцию следующим образом:
    static inline void some_inline_func(uint32_t num)
    {
        . . .
    }

    Такая функция будет доступна только для данной единицы трансляции.

    - оставить в этом исходнике всё как есть, а в каком-нибудь другом определить следующую функцию:
    void some_inline_func(uint32_t num)
    {
        . . .
    }

    Это самый дурацкий вариант, поскольку эти две реализации могут не совпадать и в зависимости от выбора транслятора ты можешь получить разное поведение.
    Ответ написан
    Комментировать
  • Как при http запросе curl не выводить ничего в консоль?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как выполнить запрос и не выводить ничего в консоль?

    Если результат запроса надо сохранить -- то открыть файл на запись и передать полученный указатель в CURLOPT_WRITEDATA. Если сохранять не надо -- установить функцию, которая будет игнорировать передаваемые ей для записи данные в CURLOPT_WRITEFUNCTION.
    Ответ написан
    Комментировать
  • Как замерять время выполнения функции?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как замерять время выполнения функции?

    Можно воспользоваться парой clock_gettime / clock_getres.

    как можно искусно замедлить выполнение

    Можно организовать искусный цикл вокруг замеряемой функции и разделить его общее время выполнения на количество итераций. Но детали зависят от того, какое именно время вы там пытаетесь померить. Т.е. если там важны эффекты от кеша, то тупой цикл может быть недостаточно искусным.
    Ответ написан
    Комментировать
  • Как задать значение последней переменной?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Имеется код вида
    int64_t a = b/c
    b и c какие-то произвольные числа
    требуется записать 0 в переменную a, если произошел SIGFPE.
    Проверять значения b и c не вариант, нужно как-то задавать значение для a в обработчике сигнала.

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

    - наиболее простой и переносимый, но не самый быстрый -- таки проверить значения b и c перед вычислениями.

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

    - следующий вариант -- нифига не простой и не переносимый -- устанавливать обработчик сигнала с помощью sigaction, заказывать доставку SA_SIGINFO и анализировать ucontext (третий аргумент) в обработчике сигнала. Сложность заключается в том, что связь между тем, что будет записано в ucontext и исходным кодом на C ни разу не очевидна. Т.е. можно извлечь из памяти по адресу info->si_addr инструкцию вызвавшую сбой, проанализировать её длину и куда она записывает результат, записать в результат 0 и передвинуть адрес возврата. Но это выглядит как неоправданное количество мороки.
    Ответ написан
  • Ошибка unhandled dwarf2 в Valgrind как можно исправить и с чем связана?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    при использовании Valgrind выпадает ошибка:

    Расскажи для начала поподробнее, как именно ты его используешь.

    Опытным путём пришёл к выводу что проблемма связана с ошибкой в самом make.

    м... а почему valgrind ругается вот на это:
    ==6410== Valgrind:   "/media/mid/Main_file_m2/Road/rank 0/libftTester/a.out"
    Ответ написан
  • Нормален ли такой код?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Нормален ли такой код?

    В каком смысле "нормален"? Он понятен, но не очень хорошо организован и делает какие-то с виду лишние действия.
    Ответ написан
  • Как инициализировать n так что бы оно работало для всех введенных n,а не только для 2?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    код работает только для 2 строк , а как записать что бы для всех которые будет вводить пользователь?

    заменить
    int k[2]={};
    на
    int k[100]={};
    Ответ написан
    Комментировать
  • Чем это достигается?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    выбором компилятора? опциями компилятора? неизвестно, ты не привёл никакой полезной информации.
    Ответ написан
    2 комментария
  • Как общаться с процессом в Linux?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Нужно написать программу, которая будет посылать в stdin программы данные и забирать из stdout.

    Что я делаю не так?


    Ты пользуешься не тем методом. pidfd_open делает совсем не то, что ты ожидаешь, см. раздел "Use cases for PID file descriptors" по приведённой ссылке.

    Взаимодействие с дочерним процессом через stdin/stdout обычно реализуется через пайп. Вот пример.

    Вот ещё пример который делает exec

    #include <unistd.h>
    
    int main()
    {
            int fd[2][2];
            pipe(fd[0]);
            pipe(fd[1]);
            pid_t pid_fork = fork();
            if (!pid_fork) {
                    // Дочерний процесс
                    close(fd[0][1]);
                    close(fd[1][0]);
                    dup2(fd[0][0], STDIN_FILENO);
                    dup2(fd[1][1], STDOUT_FILENO);
                    execl("/usr/bin/tr", "/usr/bin/tr", "l", "r", NULL);
            } else {
                    // Родительский процесс
                    close(fd[0][0]);
                    close(fd[1][1]);
                    char buf[1000];
                    ssize_t sz;
    
                    write(fd[0][1], "hello, world\n", sizeof("hello, world\n") - 1);
                    close(fd[0][1]);
                    sz = read(fd[1][0], buf, sizeof(buf));
                    if (sz > 0) {
                            write(STDOUT_FILENO, buf, sz);
                    }
            }
            return 0;
    }
    Ответ написан
    Комментировать
  • Почему после вызова Message Box, GetKeyState() не считывает состояние клавиши?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему … GetKeyState() не считывает состояние клавиши?

    Потому что чтобы GetKeyState работал, поток должен обрабатывать свою очередь сообщений (например, циклом, наподобие этого).
    Из man GetKeyState:
    The key status returned from this function changes as a thread reads key messages from its message queue. The status does not reflect the interrupt-level state associated with the hardware. Use the GetAsyncKeyState function to retrieve that information.
    Ответ написан
    Комментировать
  • Почему для драйвера мыши используется тот же порт, что и в драйвере клавиатуры?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Такие же порты используются при нахождении нажатой клавиши на клавиатуре, так как они могут быть и там и тут?

    Это называется мультиплексирование. В конце концов PS/2 -- довольно сложный интерфейс, работающий с командами, а не то чтобы клавиатура была напрямую подсоединена к одному из портов PC. См. https://wiki.osdev.org/Mouse_Input#Keyboard.2FAux_...
    Ответ написан
    Комментировать
  • Как исправить ошибку "Кадр не находится в модуле" при создании потока?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    "Кадр не находится в модуле". Подскажите с чем это может быть связано
    HANDLE h = CreateThread(
        NULL,
        0,
        factorial(gn),
        NULL,
        NULL,
        NULL
    );

    Третий параметр CreateThread -- указатель на функцию, которая будет запущена в создаваемом потоке. А у тебя записано скорее всего что-то другое. Если ты хотел запустить функцию factorial в потоке, она должна 1) иметь определённый прототип (вот такой), и 2) в функцию CreateThread надо передать её адрес, а не результат её вызова (например, так: CreateThread(NULL, 0, factorial, NULL, NULL, NULL)). 3) если ты сделаешь эти два изменения, тебе прийдётся также переделать передачу параметра в функцию factorial и получение результата её работы.
    Ответ написан
  • Как реализовать _open() для добавления своих потоков ввода-вывода?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почитать про libgloss, понять что надо самому разбирать пути переданные в параметре name и где-то хранить данные о том, что за файл и как был открыт. Понять, как именно ты хочешь "реализовать работу со своими устройствами" и… реализовать её.
    Ответ написан