Ответы пользователя по тегу C
  • Почему из-за cfgmgr32 exe стал больше на 32 мб?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Потому что .lib на винде - это статическая библиотека. Ты ее полностью к себе присоединил полностью, со всем ее кодом, функциями, переменными и т.д.
    За инфру винды не шарю, но может есть версия этой либы динамическая. Например, cfgmgr32.dll.

    P.S. я первый раз увидел, чтобы зависимости добавляли с помощью pragma. Это windows-specific ?
    Ответ написан
  • Почему GCC не видит встроенную атомарную операцию?

    AshBlade
    @AshBlade Автор вопроса
    Просто хочу быть счастливым
    Разобрался.
    Есть 2 замечания:
    1. Поближе посмотрел на сигнатуру

    bool __atomic_compare_exchange (type *ptr, type *expected, type *desired, bool weak, int success_memorder, int failure_memorder)


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

    if (__atomic_compare_exchange(&l.head->next,  (struct entry**)NULL, &new_next, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))


    Но потом начал ловить SEGFAULT. И тут пришел к 2 замечанию

    2. Не заметил следующего в документации:

    This built-in function implements an atomic compare and exchange operation. This compares the contents of *ptr with the contents of *expected. If equal, the operation is a read-modify-write operation that writes desired into *ptr. If they are not equal, the operation is a read and the current contents of *ptr are written into *expected. weak is true for weak compare_exchange, which may fail spuriously, and false for the strong variation, which never fails spuriously. Many targets only offer the strong variation and ignore the parameter. When in doubt, use the strong variation.


    Т.е. если значение во 2 аргументе не равно значению из 1, то (!!!) по месту указателя 2 записывается полученное из указателя 1 значение. А у меня там был NULL (конец списка обозначается NULL). Заменил на корректно выделенный элемент списка и все заработало

    int main(int argc, char const *argv[])
    {
        struct list l;
    
        l.head = (struct entry *)malloc(sizeof(struct entry));
        l.head->next = NULL;
        l.head->value = 123;
        struct entry *old_next = (struct entry *)malloc(sizeof(struct entry));
        old_next->next = NULL;
        old_next->value = 555;
        l.head->next = old_next;
    
        struct entry *new_next = (struct entry *)malloc(sizeof(struct entry));
        new_next->value = 444;
        new_next->next = NULL;
        if (__atomic_compare_exchange(&l.head->next, &old_next, &new_next, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
        {
            printf("ok\n");
            printf("success: next = %d\n", l.head->next->value);
        }
        else
        {
            printf("failed\n");
        }
    
        return 0;
    }


    Не хочу возиться со всякими dummy узлами, поэтому буду использовать __sync_bool_compare_and_swap. Вот такой код сработает:
    int main(int argc, char const *argv[])
    {
        struct list l;
    
        l.head = (struct entry *)malloc(sizeof(struct entry));
        l.head->next = NULL;
        l.head->value = 123;
    
        struct entry *new_next = (struct entry *)malloc(sizeof(struct entry));
        new_next->value = 444;
        new_next->next = NULL;
    
        if (__sync_bool_compare_and_swap(&l.head->next, (struct entry *)NULL, new_next))
        {
            printf("ok\n");
            printf("success: next = %d\n", l.head->next->value);
        }
        else
        {
            printf("failed\n");
        }
    
        return 0;
    }


    UPD: спасибо res2001, разобрался лучше. итоговый вариант

    #include <stdatomic.h>
    
    int main(int argc, char const *argv[])
    {
        struct list l;
    
        l.head = (struct entry *)malloc(sizeof(struct entry));
        l.head->next = NULL;
        l.head->value = 123;
    
        struct entry *new_next = (struct entry *)malloc(sizeof(struct entry));
        new_next->value = 444;
        new_next->next = NULL;
        struct entry *tmp = NULL;
        if (atomic_compare_exchange_strong(&l.head->next, &tmp, new_next))
        {
            printf("ok\n");
            printf("success: next = %d\n", l.head->next->value);
        }
        else
        {
            printf("failed\n");
        }
    
        return 0;
    }


    Просто надо создать переменную указатель, которой присвоить NULL. Также использовал atomic_compare_exchange_strong из stdatomic вместо расширения GCC - он под капотом использует __atomic_* вместо устаревшего __sync_*
    Ответ написан
    1 комментарий
  • Возможно ли сделать nested enum c/c++?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Если мы говорим про C, то так делать нельзя:
    1. Вложенные в enum определения делать нельзя - это ограничение самого синтаксиса (дока)
    2. Для использования перечислений не надо указывать само название перечисления. Т.е. не OBJ::SOMETHING, а просто SOMETHING. Т.е. видимость глобальная и нельзя дублировать названия, даже для разных enum

    В случае C++ аналогично. Есть хак - использование неймспейсов или структур для топ левела, но не в твоем случае - ты хочешь топ левел перечислениям значения задавать

    На мой взгляд тут решение:
    1. Разбить их на различные перечисления
    2. Добавить каждому префикс
    enum OBJ = 0 {
           Default = 0,
           Something_Something1 = 1,
           Something_Something1 = 2,
           Something = 7
    };
    Ответ написан
    Комментировать
  • Как вывести значение указателя без иннициализации?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    В настройках проекта отключи проверку SDL - https://stackoverflow.com/a/38445156/14109140
    Ответ написан
    Комментировать
  • Как устранить ошибку конверсии при использовании битовых полей?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Я протестировал это (со встроенным (addr >> 12) * 0xFFFFu) у себя на GCC (версия 11.4.0) и clang (14.0.0) на x86_64. Дополнительно в нескольких онлайн компиляторах. И на MinGW (версия 6.3.0).
    Нигде предупреждений подобных не встречал.
    Скорее всего это особенность версии компилятора/платформы.
    Ответ написан
  • Как следать процерку на ввод целых чисел?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Можно использовать strtol
    int parse(char* str, long* result) {
        char *end = NULL;
        *result = strtol(str, &end, 10);
        if (str == end || *end != '\0' || errno == ERANGE) {
            return -1;
        }
        return 0;
    }


    Пример:
    int main() {
        long value;
        if (parse("12313", &value)) {
            printf("Ошибка");
        } else {
            printf("Результат: %ld", value);
        }
    }
    // 123 -> Результат: 123
    // 123.0 -> Ошибка
    Ответ написан
    Комментировать
  • Что считать корректным вводом целого числа?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Целое число - это все натуральные, им противоположные и 0 - без всяких дробей, экспонент и т.д.
    Используй это определение, не усложняй себе жизнь
    Ответ написан
    Комментировать
  • Как в С можно сделать реагирование на клавишу клавиатуры без ожидания обязательного ввода (без использования стандартных библиотек)?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Можно запустить фоновый поток: он читает ввод и при получении Q/q выставляет флаг окончания.
    Псеводкод:

    int should_stop = 0;
    
    void keyboard_processor() {
         while (should_stop != 1) {
               char input = get_input();
               if (input == 'q' || input == 'Q') {
                      should_stop = 1;
                      break;
               }
         }
    }
    int main() {
        start_thread(keyboard_processor);
        while (should_stop != 1) {
              do_work();
        }
    }
    Ответ написан
  • Контринтуитивный синтаксис объявления нескольких переменных одного типа?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Объясните, что я недопонимаю?

    Все правильно понимаешь. Привыкай.

    P.S. вот поэтому и рекомендуют * писать рядом с переменной, а не у типа - const char *var , а не const char* var
    Ответ написан
    1 комментарий
  • Как создают интерфейсы в программах?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Самый низкий уровень - системные вызовы:
    Это WinAPI, X11 и т.д. Я не десктоп разработчик, но сейчас мало кто ими пользуется.

    Дальше идут фреймворки, потроенные вокруг них:
    Это wxWidgets, WTL (Windows Template Library)

    И на самом верху - полноценные языки разметки/программирования:
    Qt, XAML, Electron

    Дополнительно, никто не мешает свой фреймворк написать оконный - поверх существующих WinAPI, либо через графический фреймворк (SDL, например)
    Ответ написан
    1 комментарий
  • Почему нет записи о printf в секции .plt.dyn?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Но там запись о функции puts, а не printf.

    Это уже оптимизация компилятора. Возможно ты не передаешь printf никаких аргументов и он решил, что проще вызвать puts.
    Такое поведение уже было описано вот тут:
    The C compiler gcc likes to use its knowledge of builtin functions to manipulate code. The version of gcc in NetBSD 4.0.1/macppc will simplify the printf statement to puts("Greeting, Earth!"); so the main function effectively calls puts(3) once and then returns 0.
    Ответ написан
    1 комментарий
  • Как сделать ввод через стандартный поток (stdin) и через файл?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    2 варианта:
    - Если аргументов вообще нет, то через poll (либо select) проверяешь событие доступности данных - SO
    - Некоторые Unix программы проверяют, что если передан дефис/тире -, то читать надо из stdin (учитывай)
    Ответ написан
    Комментировать
  • Что стоит учить с или c++ или c#?

    AshBlade
    @AshBlade Куратор тега C#
    Просто хочу быть счастливым
    Это 3 совершенно различных, с точки зрения целей, языка. Лучше пойми что ТЫ хочешь, а потом выбери
    Ответ написан
    Комментировать
  • Получение значения указателя в структуре которая является указателем?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    struct SomeData {
      char* pointer;
    }
    
    ...
    
    SomeData* ptr;
    /* что нужно */
    char* ptr_ch = ptr->pointer;
    Ответ написан
    Комментировать