Ответы пользователя по тегу C
  • Как из массива байтов HEX сделать сделать DEC?

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

    byte summ[N];
    word s = x * y;
    
    for (i = 0; i < N; ++i) {
        summ[i] = s % 256;
        s /= 256;
    }
    Ответ написан
    2 комментария
  • Как устранить ошибку конверсии при использовании битовых полей?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как устранить ошибку конверсии при использовании битовых полей?

    Не использовать битовые поля. Серьёзно. Удобств на копейку а мороки на рубль.
    Ответ написан
    4 комментария
  • Почему передается некорректный адрес указателя в функцию?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Потому что переменная со спецификатором static локальна для единицы трансляции. Ты написал static button s1; в заголовочном файле, а это значит, что каждая единица трансляции в которую ты подключил этот файл получит свой собственный, независимый экземпляр переменной s1. Функция ModesInit инициализирует s1 из ModeDriver.o, а s1 из main.o останется неинициализированным.

    Исправить это можно заменив static на extern в заголовочном файле, а в одном из исходников добавив определение для переменной -- button s1;.
    Ответ написан
    1 комментарий
  • Компилятор выдаёт ошибку при попытке вызвать sizeof() относительно моего массива. Как исправить ошибку?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В C параметр функции не может быть массивом, только указателем. Синтаксис "имя с квадратными скобками" несёт тот же смысл, что и "имя со звёздочкой" когда речь идёт о параметрах функции. Если внутри функции взять sizeof от такого параметра результат будет равен sizeof от указателя. Это очень распространённая ошибка и компилятор говорит тебе об этом. Если тебе нужен размер массива переданного в функцию -- передавай его отдельно, например отдельным параметром.

    sizeof(dict)/sizeof(const char)

    Здесь ещё одна ошибка: dict -- это массив указателей (на самом деле указатель на такой массив, но по крайней мере, ты ожидал массив указателей), но ты делишь размер массива на размер const char а не на размер const char *. Во избежание таких ошибок для вычисления размера массива обычно пишут sizeof(dict)/sizeof(dict[0]).
    Ответ написан
    Комментировать
  • Контринтуитивный синтаксис объявления нескольких переменных одного типа?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    можно подумать, что при объявлении указателя, символ * относится к имени(не как часть, а как что-то зависящее от него), а не к типу.

    Если взять стандарт языка (например C99) и почитать главы Declarations, Type Specifiers и Declarators, то можно увидеть, что он разделяет declaration-specifiers, в который входят только слова и declarators, в который входят скобочки и звёздочки. Т.е. твой вывод по сути верный.

    Там же можно увидеть, что часть называемую declarator всегда можно обернуть в скобки, из чего можно извлечь следующий вывод: часть объявления вокруг которой можно поставить скобки самым широким образом относится к конкретному идентификатору, оставшаяся часть -- ко всему списку. Т.е. const char *a, b; можно превратить в const char (*a), b, но нельзя превратить в const (char *a), b или в char (const *a), b.

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

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

    Можно, если выравнивание по степени двойки. addr = (addr + alignment - 1) & -alignment
    Ответ написан
  • Почему нет инфы о библиотеках в procfc файле maps, которые в сишном коде подключены и используются?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Компилирую gcc -o outfile source.c -lpthread. То есть собираю без всяких статиков, чтобы были зависимости к подключенным библиотекам. Далее запускаю процесс, чекаю /proc/pid/maps. Там нет ни единого упоминания к libpthread.

    100500 лет назад libpthread объединилась с glibc и теперь хоть и существует отдельно, чтобы программы использующие -lpthread продолжали собираться, внутри пустая. Короче, ты выбрал неудачного кандидата для экспериментов.
    Ответ написан
    Комментировать
  • Почему появляется ошибка make: *** [Makefile:15: leak] Ошибка 1 при выполнении Makefile на C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    make: *** [Makefile:15: leak] Ошибка 1

    В linux это код ошибки "нет доступа". Начни с проверки что $(NAME) доступен для чтения и выполнения.
    Кроме того, для полноты картины стоит показывать полный лог выполнения команды make, а не только последнее сообщение об ошибке.
    Ответ написан
  • Почему в Си после main() не ставят ;?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему в Си после main() не ставят ;?

    в С при определении функции не ставят ; между объявлением и телом функции, не только для main, но и для любой другой функции. Согласно стандарту языка, например С99 приводит следующий синтаксис определения функции:
    function-definition:
        declaration-specifiers declarator declaration-list<opt> compound-statement
    declaration-list:
        declaration
        declaration-list declaration


    Этот синтаксис включает в себя также старый формат определения функции (без прототипа), в котором все аргументы должны быть объявлены между закрывающей круглой скобкой и открывающей фигурной, например (из того же стандарта):
    extern int max(a, b)
    int a, b;
    {
        return a > b ? a : b;
    }

    Однако, этот список должен содержать как минимум одно объявление и не может состоять из одной только ;.

    эта строка работает на другом языке?

    о каком "другом" языке речь?
    Ответ написан
    2 комментария
  • Как реализовать кроссплатформенную поддержку Unicode в аргументах командной строки в C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Соответственно, мне нужно конвертировать массив wchar_t в массив char перед шифрованием, а после дешифровки выполнять обратную конвертацию.

    Этот вывод не следует из исходных данных. Массив данных любого типа может быть проинтерпретирован как массив байтов, без какой бы то ни было конверсии. Т.е. исходные данные в любом формате можно зашифровать, а потом расшифровать обратно. Поэтому имеет смысл отделить преобразование форматов входных данных от шифрования/расшифровки.

    Я поменял сигнатуру функции main() на int main(int argc, wchar_t* argv[]) (пытался исправлять на wmain, но тогда ругается ld и сборка падает с ошибкой).

    То, что ты меняешь прототип main, никак не влияет на то, как она будет реально вызвана. В стандарте языка C написано, каким может быть прототип main: int main(void), int main(int argc, char *argv[]) или эквивалентным. Там же написано, что набор символов во время выполнения программы -- implementation defined, поэтому нет гарантии, что их можно обработать кросплатформенно.

    Для конвертации wchar_t* в char* я пробовал использовать функцию wcstombs, однако почему-то у меня она совершенно не работает (при попытке преобразовать строку, содержащую только латиницу, я получаю null).

    wcstombs не занимается выделением памяти, если ты "получаешь null" -- это происходит в каком-то другом месте. Ну и если ты это делаешь внутри main принимающего wchar_t* argv[], то твой код интерпретирует строку char как строку wchar_t, что добавляет хаоса.
    Ответ написан
  • Скомпилированный в GCC exe файл вылетает досрочно?

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

    Да не, это только видимость. Смотри:

    $ gcc -std=c99 -O2 -g3 -fsanitize=address main.c acp.c md5.c -o main
    $ ./main
    Base64('Hello') = "SGVsbG8="
    MD5('Hello') = "8b1a9953c4611296a827abf8c47804d7"
    =================================================================
    ==1045705==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x604000000071 at pc 0x7fb0d46486f8 bp 0x7ffd0affb580 sp 0x7ffd0affad30
    WRITE of size 33 at 0x604000000071 thread T0
        #0 0x7fb0d46486f7 in __interceptor_strcat ../../../../src/libsanitizer/asan/asan_interceptors.cpp:377
        #1 0x564b2388c0de in prepareKeys /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:263
        #2 0x564b2388cac4 in acraw /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:319
        #3 0x564b2388d8c2 in acraws /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:401
        #4 0x564b2388d8c2 in acraws_basic /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:409
        #5 0x564b2388a62e in testSimpleEncryption /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/main.c:20
        #6 0x564b2388a368 in main /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/main.c:111
        #7 0x7fb0d44461c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
        #8 0x7fb0d4446284 in __libc_start_main_impl ../csu/libc-start.c:360
        #9 0x564b2388a440 in _start (/home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/main+0x3440)
    
    0x604000000071 is located 0 bytes to the right of 33-byte region [0x604000000050,0x604000000071)
    allocated by thread T0 here:
        #0 0x7fb0d46b89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
        #1 0x564b2388fee7 in md5StringHash /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/md5.c:227
    Ответ написан
  • Может ли язык Си работать на условной stack-based машине?

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

    Есть такая штука, тезис Чёрча — Тьюринга, которая говорит, что любой алгоритм может быть реализован машиной Тьюринга.

    Будут ли какие-то проблемы для генерации кода из Си в ассемблер для подобной машины?

    Для этого надо уточнить, что такое "проблемы".
    Ответ написан
  • Что не так с Futex?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему такая ошибка со своим mutex

    потому что pthread_t шире чем int owner, и как следствие этот тест не работает.
    Ответ написан
  • Почему невозможно получить доступ к каталогу?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему ls не работает

    потому что main в процессе демонизации меняет текущий каталог на /. Если запускать его с полным путём (например ./main `pwd`/mntpoint) -- то становится лучше. Но всё ещё не работает, потому что при использовании обработчиком запроса на доступ к каталогу этого же самого каталога происходит бесконечная рекурсия и исходный запрос не завершается.
    Лучше спроси, как я это понял.
    Ответ написан
  • С чего начать, чтобы написать свою библиотеку по загрузке бинарника в микроконтроллер?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    У твоей задачи есть как минимум два решения. Одно, попроще: взять готовую программу прошивки, посмотреть, как она работает, написать библиотеку реализующую то же самое. Другое, посложнее: начать со спецификации контроллера который ты собираешься прошивать и раскручивать зависимости с той стороны. Поскольку ни то, ни другое решение сами по себе большого смысла не имеют (потому что есть уже программы для прошивки), тебе надо решить, чего ты сам хочешь получить от этого упражнения.

    Есть, может, какие-то специальные книги по этой теме?

    Спецификации на контроллер, а недостаток большой картины можно покрыть википедией и всяким osdev.org
    Ответ написан
    Комментировать
  • Возможно ли как-то использовать обычную функцию заместо макро-функции?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    #define BIT_SET(port, bit) (port |= (1 << bit))
    
    int main(void)
    {
        BIT_SET(PORTB, PORTB0);
    }


    вот такой вариант, с макро-функцией, работает, так как это просто текстовая замена

    Он работает, потому что с таким определением BIT_SET PORTB не может быть определён просто как 0x04. Потому что просто текстовая замена 0x04 |= 1 << 0 не имеет смысла. Он определён как volatile ссылка на память с адресом 0x04. Когда ты научишься передавать ссылку на такую память в функцию, функция тоже начнёт работать.
    Ответ написан
    3 комментария
  • Почему библиотека не ставится?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Пытаюсь поставить библиотеку, не получается
    почему?
    file INSTALL cannot find
    "/home/durachok/HTTPParser/build/_deps/ethernet-src/include/Ethernet.h": No
    such file or directory.


    Потому что здесь написана какая-то фигня, ссылающаяся на несуществующий файл.
    Ответ написан
    Комментировать
  • Не могу понять почему не работает USER тред?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему не работает USER тред?

    Потому что, опять, ты вызываешь makecontext не задав uc_link. thread_func1 отрабатывает, а дальше гонка между вызовом thread_func2 из monitor_thread и завершением программы из-за возврата из функции контекста в контексте созданном с uc_link == NULL.

    Но и без этого код выглядит загадочно. Непонятно зачем мешать в одну кучу контексты и clone. Непонятно зачем дублировать указатель на функцию в Thread::func и в Thread::context. Непонятно зачем контексты, если schedule их не использует. Непонятно, зачем monitor_thread занимается активным ожиданием Thread::active. Непонятно, зачем функции потоков лезут в потроха Thread. Короче, этому коду не хватает идеи.
    Ответ написан
  • Почему не печатается?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему не печатается "custom thread completed"

    Потому что thread->context.uc_link = NULL; в строке 27, а, согласно man swapcontext:
    If the successor context pointer is NULL, the thread exits.


    Исправить можно, например, так:
    int custom_thread_create(custom_thread *thread, ucontext_t *link, void (*start_routine)(void*), void *arg) {
        …
        thread->context.uc_link = link;
        …
    }
    …
        ucontext_t main_context;
        getcontext(&main_context);
    
        if (custom_thread_create(&thread, &main_context, print_message, (void*)message) == 0) {
    …
    Ответ написан
  • Где найти такую CLI?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Хочется как-то отойти от указания всех параметров а считать что есть некий контекст.

    Я вот так делаю в подобных случаях. Т.е. загружаю конфигурацию из конфиг-файла если он есть, а потом поверх неё -- из параметров командной строки. Среди которых могут быть другие конфиг-файлы.
    Ответ написан
    Комментировать