Ответы пользователя по тегу C
  • Как реализовать на с или assembler асинхронную выборку из RAM?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Как реализовать на с или assembler асинхронную выборку из RAM?

    Например так. Это часть реализации memcpy для MIPS. Этот код не выглядит асинхронным, но написан именно так (сначала групповая загрузка в разные регистры, потом изменение базового адреса загрузки, потом групповое сохранение, потом изменение базового адреса сохранения) с рассчётом на то, что процессор сможет, в том числе, перекрыть во времени операции загрузки, арифметики и сохранения данных.
    Ответ написан
  • Include/header guards зачем?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Зачем нужны header guards если в заголовочных файлах мы пишем только объявление функции?

    Не всегда мы пишем только объявления. Иногда мы там пишем определения, например определяем структуры, или псевдонимы типов (typedef). Повторное определение таких вещей -- ошибка. Тут ты можешь сказать: "но я подключаю хедер в каждый исходник только один раз". Да, пока проект простой можно это отследить. Но когда одни хедеры начинают подключать другие хедеры это становится делать сложнее. header guards упрощают развитие проекта.
    Иногда между хедерами бывают циклические зависимости, header guards позволяют разорвать цикл.
    Ответ написан
  • Почему при записи в /proc/ система зависает?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    static struct file_operations process_sched_add_module_fops = {
    …
    proc_create(PROC_CONFIG_FILE_NAME,0777,NULL,&process_sched_add_module_fops);

    Я думаю, что это основная ошибка: proc_create принимает указатель на структуру proc_ops, а не на file_operations. Компилятор должен был бы что-нибудь сказать в этом месте, ты не читаешь его предупреждения?

    static ssize_t process_sched_add_module_write(struct file *file, const char *buf, size_t count, loff_t *ppos)

    А здесь ты потерял аннотацию __user у параметра buf. Этот буфер приходит из юзерспейса, по этой причине ты не можешь лезть в него напрямую функцией kstrtol.
    Ответ написан
  • Почему выводится только первое слово из scanf() в printf() в Си?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Почему?

    Потому что scanf("%s", name) сканирует поле до первого пробельного символа.
    Если ты хочешь строчку до конца строки используй, например, scanf("%[^\n]", name)
    Ответ написан
  • Почему этот код работает?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    copy_from_user(ips[i], buffer,256);
    
       	printk(KERN_INFO "ips: %s \n", ips[i]);
       	i++;
    
       	if(strncmp(ips[0],"wh",2)==0){

    почему он работает,

    Во-первых этот код неполный, он использует переменные определённые где-то ещё, от того как именно они определены зависит насколько он "работает".
    Во-вторых, по тому что видно, работает он, скажем, так себе:
    - он печатает строчку принятую из юзерспейса без ограничения длины. Если юзер не поставил 0-терминатор, то напечатает мусор из пространства ядра за нефиг делать.
    - копирование происходит в ips[i], где i увеличивается с каждым вызовом, а анализ всегда смотрит на ips[0].
    - в прототипе функции отсутствует аннотация __user у параметра buffer.

    как его можно переписать, чтобы было удобнее читать?

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Почему выводит только первую строку а остальные что-то непонятное?

    int print_arr(int str, int stlb, int matr[][stlb]){
    ...
    }
    
    int mass[10][10];
    ...
    print_arr(N, L, &mass[k][i]);


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

    Если уж ты решил использовать VLA, то делай это последовательно, например так:

    int  main()
    {
        int L = 0, N = 0, k, i;
        scanf("%d", &N);
        L=N;
        int mass[N][L];
        for(k = 0; k < N; k++){
            printf("[%d]\n", k);
            for(i = 0; i < L; i++){
        	    scanf("%d", &mass[k][i]);
            }
        }
        printf("matrix NxN\n");
        print_arr(N, L, mass);
        return 0;
    }
    Ответ написан
  • Почему не работает мой код С?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Судя по коду, там где написано scanf("%d", &d); имелось в виду scanf("%d", &nUm);.

    nUm = nUm % d;// делим на него

    Здесь должно быть написано nUm = nUm / d;// делим на него

    Кроме того, d может делить nUm больше чем 1 раз, это можно проверить сразу, и разделить nUm на d столько раз, сколько можно. Тогда не надо будет делать этого:
    d=2; //обнуляем переменную d
    Ответ написан
  • Как определить исключение "число не является вещественным"?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    printf(file, "\nОшибка, недопустимые значения");

    он записал обрывок сообщения:
    "стимые значения"
    а почему?

    Потому что у printf первый аргумент -- строка, а не файл.

    fprintf(file, "\nОшибка, недопустимые значения");

    А вот этим ты свой исходный файл испортил.

    И до кучи
    fscanf(file, "%f", &num) == true

    проверяй на == 1. fscanf возвращает число (отсканированных полей), а не признак успеха.
    Ответ написан
  • Как обработать -- в getopt_long?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Можно что-то такое вставить после цикла while:
    if (optind < argc) {
                    int i;
    
                    for (i = optind; i < argc; ++i)
                            printf("> %s\n", argv[i]);
            }
    Ответ написан
  • Проблемы с библиотекой math.h Проблемы с cos?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    main.cpp:23:42: error: no matching function for call to ‘cos(float, double)’

    Вот же он тебе пишет, и даже стрелочкой тыкает, что ты пропустил скобку, и вместо cos(2 * a) у тебя получилось cos(2 * a, 2.0).
    Ответ написан
  • Как правильно отсортировать структуру по полю динамической строки с помощью qsort?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    qsort(variables, amount_of_variables - 1, sizeof(memoryCell), struct_cmp_by_name);

    Ну, всё правильно написано, если ты действительно хочешь отсортировать массив без последнего элемента.
    Ответ написан
  • Парсинг строки не через strtok на СИ. В чем заключается ошибка?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    sizeof(char)

    Всегда равен 1 согласно стандарту, сэкономь нам и себе время.

    while(isdigit(string[j]) || isalpha(string[j]))
                {
                    buf = (char *)realloc(buf, ++k * sizeof(char));
                    buf[k - 1] = string[j];
                    j++;
                }

    После этого цикла buf не закрыт 0-терминатором, работать с ним как со строкой нельзя.

    parsed_string[size - 1] = (char *)malloc(strlen(buf) * sizeof(char));
    strcpy(parsed_string[size - 1], buf);

    Переполнение буфера, потому что strcpy копирует strlen(buf) символов строки + 1 нулевой байт.
    Ответ написан
  • Почему возможно объявление глобальной переменной структурного типа до объявления этого структурного типа?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Почему возможно объявление глобальной переменной

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

    В твоём втором примере struct interval b -- это определение переменной, выделяющее для неё место на стеке. Но его можно переписать, чтобы b тоже стало объявлением, например так:
    int main ()
    {
      extern struct interval b;
      struct interval 
      {
        int first;
        int second;
      };
    }


    Возвращаясь обратно к первому примеру, struct interval b; -- это tentative definition с внешней линковкой. Стандарт (С99) говорит о нём следующее (6.9.2:2):

    A declaration of an identifier for an object that has file scope without an initializer,
    and without a storage-class specifier or with the storage-class specifier static, constitutes
    a tentative definition. If a translation unit contains one or more tentative definitions for
    an identifier, and the translation unit contains no external definition for that identifier,
    then the behavior is exactly as if the translation unit contains a file scope declaration of
    that identifier, with the composite type as of the end of the translation unit, with an
    initializer equal to 0.


    Самое важное здесь -- as of the end of the translation unit, т.е. тип объекта из tentative definition таки должен быть определён, но не до появления этого tentative definition, а до конца единицы трансляции (или раньше, если вдруг встретится определение с инициализацией этого объекта).
    Ответ написан
  • Как найти неправильную работу с памятью?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Как найти неправильную работу с памятью?

    Откомпилируй и слинкуй свою программу с опцией -g, тогда valgrind тебе прямо в проблемную строчку тыкнет.
    Ответ написан
  • Почему вывод программы через дебаггер отличается от вывода при запуске из оболочки?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    if(rotor[i]==tmp)

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Я не совсем понимаю, как мне прописать сравнение текущего элемента массива в цикле for со всеми остальными его элементами

    Возможное решение -- сделать это во вложенном цикле.
    Другое возможное решение -- воспользоваться хеш-таблицей (но её реализация всё равно будет содержать циклы внутри).
    Ответ написан
  • Исходники стандартной библиотеки?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Как это понимать? Это что вся функция, которая нам устанавливает связь с сервером?

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

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Вот так не работает: button_left.button_port = "PORTD";
    А так работает:
    struct button button_left = {"PORTD", 6, 0, 0, 0, 12};

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

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Unable to find an entry point named 'foo' in shared library 'lib.so'.

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

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

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Почему-то меню показывается два раза после того, как я введу что-либо.
    scanf("%c", &choice);

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