Ответы пользователя по тегу C
  • Исходники стандартной библиотеки?

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

    Это заглушка, на случай, если нет другой реализации этой функции.
    Для linux другая реализация есть, она находится в sysdeps/unix/sysv/linux/connect.c, но всё что она делает -- это системный вызов, обёрнутый в манипуляции с pthread-cancellation.

    Можно посмотреть на реализацию системного вызова в ядре. Начать можно отсюда, это диспетчер системного вызова connect. Реализация connect для TCP/IPv4 находится здесь.
    Ответ написан
    Комментировать
  • Почему возникает ошибка при обращении к struct?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Вот так не работает: button_left.button_port = "PORTD";
    А так работает:
    struct button button_left = {"PORTD", 6, 0, 0, 0, 12};

    Почему возникает ошибка при обращении к struct?

    Ты видишь разницу между этими двумя строчками? Первая генерирует код который присваивает значение одному полю структуры. Она должна быть там, где можно писать код -- в теле какой-нибудь функции. Нельзя написать её вне всех функций.
    Вторая генерирует инициализированную структуру. Её можно написать и вне всех функций -- тогда она будет генерировать глобально видимую структуру инициализированную до начала выполнения программы. Её можно написать и внутри функции -- тогда она будет генерировать автоматическую переменную и инициализировать её в момент "выполнения".
    Ответ написан
    2 комментария
  • Как запустить из C# код C, использующий код на ассемблере без инлайна?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Unable to find an entry point named 'foo' in shared library 'lib.so'.

    Убрать static из static int foo(void).

    код C, использующий код на ассемблере без инлайна?

    проблема не в ассемблере
    Ответ написан
  • Почему показывается 'меню' 2 раза?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему-то меню показывается два раза после того, как я введу что-либо.
    scanf("%c", &choice);

    Потому что вот этот scanf читает единственный символ из потока ввода, а чтобы ввести, например, 1, нужно нажать '1', а за ней следом 'enter'. '1' останется сама собой и будет прочитана первым scanf, а 'enter' превратится в '\n' и будет прочитан вторым scanf.
    Чтобы этого избежать можно читать так:
    scanf(" %c%*[^\n]", &choice);
    Пробел перед %c проглотит все пробельные символы, %*[^\n] проглотит хвост строки после первого прочитанного не-пробельного символа.
    Ответ написан
    4 комментария
  • Не работает структура объявленная в заголовочном файле?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    htype_t htval;
    htval.num = 10;

    А почему бы для разнообразия не писать по правилам языка, например так (если, таки, С):
    htype_t htval = {.num = 10};
    или так (если, таки, С++):
    htype_t htval = {10};
    или даже так:
    htype_t htval;
    
    int main(int argc, char* argv[]) {
        htval.num = 10;
    Ответ написан
    Комментировать
  • Почему при перегрузке функции через макрос, появляются предупреждение в _Generic на каст?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Хотелось бы знать причину предупреждений, это стандартное поведение или несовершенство препроцессора?

    Препроцессор-то тут ни при чём. Если посмотреть в
    препроцессированный код,

    _Generic((1), int : _Generic((2), int : fnk(1, 2,
    # 37 "generic.c" 3 4
       ((void *)0)
    # 37 "generic.c"
       ), char * : fnk(1, 0, 2)));
    
        printf("\n2.2)---------\n");
        _Generic((1), int : _Generic(("2"), int : fnk(1, "2",
    # 40 "generic.c" 3 4
       ((void *)0)
    # 40 "generic.c"
       ), char * : fnk(1, 0, "2")));

    то видно, что выражение выбираемое _Generic имеет правильные типы, но выражения в других ветках при этом имеют неправильные типы. Предупреждение об этом.

    Пофиксить можно было бы заведя две разные функции для int и char * и выбирая в _Generic только нужную функцию, а не всё выражение. Типа того:

    void fnk_int(uintmax_t A, uintmax_t B){
    ...
    }
    void fnk_pchar(uintmax_t A, char *B){
    ...
    }
    
    #define FFF_B(A, BC) \
            _Generic((A), \
                    int : _Generic((BC), \
                            int : fnk_int, \
                            char * : fnk_pchar)(A, BC))
    Ответ написан
    5 комментариев
  • Почему не переворачивает строку?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что не так?
    char *str = "hello";

    Вот эта строчка не так. То, что компилятор разрешает так делать -- это анахронизм и отсутствие мало-мальской диагностики. "hello" может находиться (и в твоём случае, похоже, и находится) в области памяти доступной только для чтения, изменять эту строку нельзя. Правильно было бы написать так:
    char str[] = "hello";
    Если сделать эту замену, то код будет выделять место для массива str на стеке, менять такой массив можно.
    Ответ написан
    5 комментариев
  • Как практиковаться системному програмиисту?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как практиковаться

    Ввязываться в проекты интересующей тематики, решать их реальные проблемы.
    Если интересен линукс, наиболее на мой взгляд благоприятная точка входа для новичка -- через тестирование ядра.
    Ответ написан
    Комментировать
  • Что лучше начать читать про API linux или про ядро Linux?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Linux API. Исчерпывающее руководство

    С него. Потому что это именно то, что нужно чтобы научиться "программировать под линукс".
    Ответ написан
    Комментировать
  • На Си функции не могут быть вложенными друг в друга?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В соответствии со стандартами языка -- не могут. Но есть расширения (в частности, у gcc), позволяющие определять функции вложенные в другие функции.
    Зачем? Вложенные функции -- это лямбды, которые были до лямбд С++.
    Ответ написан
    Комментировать
  • Препроцессоры вставляют файл целиком через #include или частично?

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

    Да.

    Т.е. препроцессоры глупые и пихают весь код из подключенных заголовочных файлов. Но дело в том, что в заголовочных файлах C кода как такового почти нет. Обычно там определения типов и объявления функций. Определения функций скомпилированы и находятся в библиотеках. И компоновщик достаёт из библиотек и линкует только те функции, которые реально используются.

    P.S. Т.е. если перефразировать вопрос, то он бы звучал так: можно ли выборочно подключать только необходимые функции из подключаемых библиотек?

    Это происходит по умолчанию.

    Если первой строчкой кода записать #include <stdio.h>

    Загляни ради интереса в stdio.h и попробуй найти там определение (не объявление) функции printf.
    Ответ написан
    2 комментария
  • Как скопировать значение переменной окружения через указатель в СИ?

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

    Для этого надо понимать структуру данных. Структура переменных окружения такова: есть символьный массив содержащий текст всех переменных, и есть массив указателей, содержащий указатели на начало каждой переменной в первом массиве. Копировать указатели из второго массива но не копировать сами переменные бесполезно.

    С другой стороны, в этом задании вообще не нужно ничего копировать. И пользоваться strtok тоже не нужно. Нужно искать длину названий переменных. Сделать это можно так:
    #include <string.h>
    
    void ShortNames(char **arr, int num)
    {
        int i;
        for (i = 0; arr[i]; ++i) {
            int len = strchr(arr[i], '=') - arr[i];
            if (len <= num)
                printf("%.*s\n", len, arr[i]);
        }
    }
    Ответ написан
  • Как задать поведение препроцессора C в GCC?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Смысл его прост: отменить действие макроса в определенной части кода, а по ее истечении восстановить этот макрос.

    Таким образом этого сделать нельзя. Потому что в месте где написано #define temp func значение макроса func не подставляется. В temp попадает буквально слово func. После #undef func содержимое макроса func будет потеряно. Это поведение предписано стандартом, мне неизветсны опции компилятора, которыми его можно было бы изменить. См. eelis.net/c++draft/cpp.replace#10 и eelis.net/c++draft/cpp.rescan

    Но если внести ещё один уровень косвенности, то можно сделать чтобы это работало. Например:
    #define foo bar
    #define func foo
    ...
    #undef func
    ...
    #define func foo
    Ответ написан
    3 комментария
  • В чем проблема в коде?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    пока z не сделаетется в 1024/1000000*255*20 секунд ждем
    while (z < 21) 
    {   
        if (TCNT0 == 255) 
        {
            z++;    
        };
    };

    Русским языком говоря , нажал кнопку подождал примерно 5.2 с

    Не, ты тут подождал какое-то другое время. Потому что если в таймер заходит clkio/1024, то TCNT будет равен 255 далеко не один цикл.

    Код не работает в протеусе и сыплет ошибками

    Ну так он же пишет тебе адрес, PC=0x005e, посмотри что по этому адресу происходит.
    Ответ написан
  • Почему при удалении файла fwrite не возвращает ошибку?

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

    Ты не файл удаляешь, а только его имя из каталога. Файл остаётся до тех пор, пока не будет закрыт последний дескриптор указывающий на него. Все процессы открывшие файл до удаления его имени будут иметь к нему доступ до тех пор. В этом можно убедиться заглянув в /proc/<pid>/fd твоего процесса.
    Ответ написан
    5 комментариев
  • Каким образом здесь происходит упаковка структур?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    каким образом тут спаковалась структура?

    На картинке явно первое поле (31 байт), второе поле (16 байт), дырка в 1 байт, третье поле (4 байта), четвёртое поле (4 байта).
    Ответ написан
  • Как изменить исходный код vlc что бы дописывать в лог временные метки фильтра motiondetect?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В структуре picture_t которая передаётся в Prepare* и в Filter есть поле date, возможно оно вам поможет.
    Ответ написан
    Комментировать
  • Откуда появляется ошибка?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    mid = high + low;
    guess = arr[mid];

    Первая очевидная ошибка здесь: сумму надо бы разделить пополам.

    else if (guess < item)
      low = mid - 1;

    Вторая очевидная ошибка здесь: mid может быть равен 0, а значит low может вылезти за пределы массива снизу.

    С условием выхода из цикла поиска при отсутствии искомого значения в массиве тоже не всё ОК.

    int arr[length];
    Если length = 2147483647, то программа вообще отказывается работать.

    Ты пытаешься разместить массив размером 8ГБ на стеке. Как видишь, это не очень хорошая идея.
    Ответ написан
    1 комментарий
  • Как в gcc сохранять объектные файлы(в другой папке)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как в gcc сохранять объектные файлы

    Опция -o -- путь к результату, препроцессирования/компиляции/линковки. Научи свой Makefile подставлять правильный путь в эту опцию.
    Ты скажешь "а у меня 100500 исходных файлов компилируется разом". Ответ -- а не надо так делать. Компилятор всё равно вызывается каждый раз новый. Напиши правило компилирующее один файл в нужный каталог -- и выполни его по разу для каждого исходника. Например так:
    NAME = calc
    
    SRC = main.c \
      parser.c \
      ft_lib/ft_atoi.c \
      ft_lib/ft_putchar.c \
      ft_lib/ft_putnbr.c
    
    BUILDDIR=build
    OBJ = $(addprefix $(BUILDDIR)/,$(subst /,_,$(patsubst %.c,%.o,$(SRC))))
    
    FLAGS = #-Wall -Wextra -Werror
    
    all: $(NAME)
    
    $(NAME): $(OBJ)
      gcc $(OBJ) -o $(NAME)
    
    define CC_RULE =
    $(BUILDDIR)/$(subst /,_,$(patsubst %c,%o,$(SOURCE))): $(SOURCE)
      gcc $(FLAGS) -c $< -o $@
    endef
    
    $(foreach SOURCE,$(SRC),$(eval $(call CC_RULE,$(SOURCE))))
    
    clean:
      rm -f $(OBJ)
    
    fclean:
      rm -f $(NAME)
    
    re: fclean all


    Смотри: я сделал список объектников из $(SRC), написал генератор CC_RULE, который для любого исходника генерирует правило компиляции его в объектник под $(BUILDDIR) и вызвал его для всех исходников в $(SRC).

    Это забавное развлечение, но гораздо практичнее воспользоваться существующей системой сборки: autotools/CMake/...
    Ответ написан
    4 комментария
  • База Данных на СИ. Почему не компилирует далее?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    scanf_s("%[^/n]s", b.book_name);
    printf_s("Enter the price and quantity\n"); // Не появляется далее это.

    Не появляется, потому что у тебя в предыдущей строке ерунда написана.
    Ответ написан