Задать вопрос
Ответы пользователя по тегу C
  • Почему поле fd в событии epoll_event не задано?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    e.data.fd = cfd;
    e.data.ptr = (void*)cfd;


    epoll_data -- это union, не нужно его инициализировать сначала одним, а потом другим:
    typedef union epoll_data {
                   void    *ptr;
                   int      fd;
                   uint32_t u32;
                   uint64_t u64;
               } epoll_data_t;
    
               struct epoll_event {
                   uint32_t     events;    /* Epoll events */
                   epoll_data_t data;      /* User data variable */
               };


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

    в документации сказано, что там должно быть значение, которое было в поле data во время вызова epoll_ctl.

    Кроме того, 0 -- вполне нормальный файловый дескриптор.
    Короче, я попробовал, у меня работает. Если у тебя не работает -- приведи весь код.
    Ответ написан
    1 комментарий
  • Си. Что означает данное высказываение?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Желательно привести наглядный пример.


    Программа состоящая из следующих двух файлов может не собраться, потому что первые 6 символов имён функций из второго файла идентичны:

    void f123456();
    void main()
    {
        f123456();
    }

    void f123456(void)
    {
    }
    
    void f123457(void)
    {
    }
    Ответ написан
    1 комментарий
  • Как реализовать функцию map?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    l=[a_1,..,a_n] – некоторый список элементов типа T, а f:T→T, то:
    map(f,l)↦[f(a_1 ),..,f(a_n )]
    Не понятно что она делает и как ее реализовать.


    Почему непонятно что делает? Вы же сами написали: применяет функцию f к каждому элементу входного списка.
    Как её реализовать -- зависит от представления списка, от того, насколько строго хочется обойтись с типами и от того, насколько хочется следовать стандарту.
    Например, можно сделать так:
    #include <stddef.h>
    
    struct list {
        struct list *next;
    };
    
    struct list *map(void f(struct list *p), struct list *l)
    {
        struct list *i;
        for (i = l; i != NULL; i = i->next)
            f(i);
        return l;
    }
    
    struct list_int {
        struct list list;
        int i;
    };
    
    void process_int(struct list *l)
    {
        struct list_int *p = (struct list_int *)l;
        ++p->i;
    }
    
    int main()
    {
        struct list_int l[] = {
            [0] = {
                .list.next = &l[1].list,
                .i = 1,
            },
            [1] = {
                .i = 2,
            },
        };
        map(process_int, &l[0].list);
    }
    Ответ написан
    1 комментарий
  • Почему неправильно преобразуется структура?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Из за чего это ?

    Из-за выравнивания полей данных в структуре и из-за того, что long -- 8 байт. В структуре my_struct_in у тебя идут подряд short, short и long. Первые два short -- выравнены, а чтобы выравнять long компилятор вставил перед ним в структуру дырку длиной в 4 байта. Можно напечатать offsetof(struct my_struct_in, addr) чтобы в этом убедиться.

    Что делать? Использовать типы фиксированной ширины (uint32_t addr, если имелся в виду IP адрес). Паковать структуры (если выравнять нельзя), либо располагать поля согласно их натуральному выравниванию.
    Ответ написан
    3 комментария
  • Как вывести flags как в objdump?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как на Си вывести флаги в том же формате, что делает команда objdump?

    А в код-то не посмотреть никак?
    static void
    dump_bfd_header (bfd *abfd)
    {
      char *comma = "";
    
      printf (_("architecture: %s, "),
              bfd_printable_arch_mach (bfd_get_arch (abfd),
                                       bfd_get_mach (abfd)));
      printf (_("flags 0x%08x:\n"), abfd->flags & ~BFD_FLAGS_FOR_BFD_USE_MASK);
    
    #define PF(x, y)    if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
      PF (HAS_RELOC, "HAS_RELOC");
      PF (EXEC_P, "EXEC_P");
      PF (HAS_LINENO, "HAS_LINENO");
      PF (HAS_DEBUG, "HAS_DEBUG");
      PF (HAS_SYMS, "HAS_SYMS");
      PF (HAS_LOCALS, "HAS_LOCALS");
      PF (DYNAMIC, "DYNAMIC");
      PF (WP_TEXT, "WP_TEXT");
      PF (D_PAGED, "D_PAGED");
      PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
      printf (_("\nstart address 0x"));
      bfd_printf_vma (abfd, abfd->start_address);
      printf ("\n");
    }
    Ответ написан
  • Оцените код. Как можно заменить goto?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    while (size <=0)//проверка ввода
            goto check;//в случае неудачи, переход по метке check на 40 строку

    это
    if (size <= 0)
        break;


    goto mark;

    это просто continue; в первом случае и просто ничего во втором.
    Ответ написан
    Комментировать
  • Почему затирается часть массива в Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert

    void get_disks(char * allDisks[])
    {
      char buf[128];
      ...
      for (char *s = buf; *s; s += strlen(s) + 1)
      {
          ...
          allDisks[i] = s;
          ...
          allDisks[7] = "ABC";
          allDisks[8] = "DEF";
      }
    }


    После прохождения массива функцией get_files список дисков исчезает, но "ABC" и "DEF" остаются.
    Подскажите, почему так происходит, куда теряются первые строки и как исправить?

    Так происходит потому что ты кладёшь в allDisks указатели на стековый массив buf, который разрушается после выхода из функции get_disks. А строчки "ABC" и "DEF" -- константные строчки, существуют всё время выполнения программы.
    Исправить можно, например, выделив память для строчек, которые записываются в allDisks:

    void get_disks(char * allDisks[])
    {
      char buf[128];
      int i = 0;
    
      GetLogicalDriveStringsA(sizeof(buf), buf);
      for (char *s = buf; *s; s += strlen(s) + 1)
      {
        if (GetDriveTypeA(s) == 2 || GetDriveTypeA(s) == 3)
        {
          allDisks[i] = strdup(s);
          ++i;
    
          allDisks[7] = "ABC";
          allDisks[8] = "DEF";
        }
      }
    }
    Ответ написан
    Комментировать
  • Почему программа работает неправильно?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему я неправильно ссылаюсь к указателю в структуре?
    zmienna_strukt.a=NULL;
    ...
    scanf("%s", wsk->a);

    Ссылаешься правильно, но указатель указывает в NULL. Читать туда scanf'ом нельзя. Чтобы можно было читать -- надо чтобы указатель указывал в выделенную память достаточного размера. Например так:
    struct morgan zmienna_strukt;
        struct morgan *wsk;
        unsigned char buf[100];
    
        wsk=&zmienna_strukt;
    
        printf("Впиши значение: ");
        fflush(stdout);
        scanf("%d", &zmienna_strukt.b);
        printf("%d \n\n", zmienna_strukt.b);
    
        zmienna_strukt.a=buf;
        buf[0] = 0;
        printf("%s \n\n", zmienna_strukt.a);
    
        printf("Впиши значение: ");
        fflush(stdout);
        scanf("%s", wsk->a);
        printf("%s \n\n", wsk->a);
    Ответ написан
    1 комментарий
  • Как улучшить код в плане читаемости?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Зачем столько всего разного?
    Зачем переводить числа в целочисленные массивы цифр, почему было не оперировать со строчками? Зачем изобретать свои itoa и atoi? Зачем сортировать а потом делать reverse, почему нельзя просто поменять условие сортировки?
    Почему было не сделать так:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int cmp_min(const void *a, const void *b)
    {
        int va = *(const char *)a;
        int vb = *(const char *)b;
        return va - vb;
    }
    
    static int minimize(int v)
    {
        char str[sizeof(int) * 3 + 1];
        int i;
    
        sprintf(str, "%d", v);
        qsort(str, strlen(str), 1, cmp_min);
        if (str[0] == '0') {
            for (i = 0; str[i]; ++i) {
                if (str[i] != '0') {
                    str[0] = str[i];
                    str[i] = '0';
                    break;
                }
            }
        }
        sscanf(str, "%i", &v);
        return v;
    }
    
    static int cmp_max(const void *a, const void *b)
    {
        int va = *(const char *)a;
        int vb = *(const char *)b;
        return vb - va;
    }
    
    static int maximize(int v)
    {
        char str[sizeof(int) * 3 + 1];
    
        sprintf(str, "%d", v);
        qsort(str, strlen(str), 1, cmp_max);
        sscanf(str, "%i", &v);
        return v;
    }
    
    int main()
    {
        int a, b;
        int result_a, result_b;
    
        scanf("%i %i", &a, &b);
        result_a = a < 0 ? -minimize(-a) : maximize(a);
        result_b = b < 0 ? -maximize(-b) : minimize(b);
        printf("%d\n", result_a - result_b);
        return 0;
    }
    Ответ написан
    Комментировать
  • Как получить результат функции в main при работе с матрицами?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    sum_of = sum(matrix[][]);

    должно стать
    sum_of = sum(n, matrix);

    int sum (int n, int matrix[n][n]) {
        int sum = 0;
        for (int j = 0; j < n; ++j){
            for (int i = 0; i < n; ++i){
                if (j == i){
                    sum += matrix[j][i];
                }
            }
        }
        return sum;
    }

    Это, конечно, работает, но лучше написать так:
    int sum (int n, int matrix[n][n])
    {
        int sum = 0;
        for (int i = 0; i < n; ++i) {
            sum += matrix[i][i];
        }
        return sum;
    }
    Ответ написан
    Комментировать
  • Для чего нужен return?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    float del (float a, float b)
    {
        float res;
        ...
        res = ...;
        ....
        return res;
    }
    ....
    float result = del (num1, num2);

    что делает "return res" во втором куске кода? То есть в переменную res записывается деление числа А и Б. А потом оно куда-то там возвращается..

    Это значение, которое вернётся из функции в точку вызова. В примере выше оно будет присвоено переменной result.
    Ответ написан
    Комментировать
  • Как программно реализовать текстовый протокол SCPI на микроконтроллере?

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

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Если первым параметром дать большое число, то программа выполняется очень долго.

    А если вместо суммирования чисел воспользоваться формулой суммы арифметической прогрессии n * (n + 1) / 2 ?
    Насколько велико "большое число"?
    Ответ написан
    1 комментарий
  • "Нечитаемый" код?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    for(char* pnew_char = new_char; *pnew_char++ = *--pchar;);

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

    for(; *pchar; ++length, ++pchar);

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

    for(char* pnew_char = new_char; *pnew_char++ = *--pchar;);

    Так делать (писать тело цикла в его поле для условия выхода, равно как и писать его в последнем поле) не стоит, потому что всему своё место, а ошибку в этом цикле ты уже допустил.
    Ответ написан
    7 комментариев
  • Как вывести символ через канал?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В каком месте может быть ошибка?

    man pipe: писать можно только в fd[1], читать -- только из fd[0].
    Канал однонаправленный, т.е. для двунаправленной коммуникации нужно открывать два канала.
    Должно быть так:
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/wait.h> 
    
    int main(int argc, char **argv) {
    
            int fd0[2], fd1[2], n;
            char c;
            pipe(fd0);
            pipe(fd1);
    
            if (!fork()) {
                    close(fd0[0]);
                    close(fd1[1]);
    
                    write(fd0[1], "c", 1);
    
                    sleep(1);
    
                    if ((n = read(fd1[0], &c, 1)) != 1) {
                            printf("Дочерний процесс. Результат чтения: %d\n", n);
                            exit(0);
                    }
    
                    printf("Дочерний процесс прочитал: %c\n", c);
                    exit(0);
            }
            close(fd1[0]);
            close(fd0[1]);
                                                                                                                                                                                                                                                                              
            write(fd1[1], "p", 1);
            if ((n = read(fd0[0], &c, 1)) != 1) {
                    printf("Родительский процесс. Результат чтения: %d\n", n);
                    exit(0);
            }
    
            printf("Родительский процесс прочитал: %c\n", c);
            exit(0);
    
            return 0;
    }
    Ответ написан
    3 комментария
  • Что есть структура, а что оператор в C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В стандарте языка используются термины "expression" (например, printf("something\n"), без точки с запятой -- это expression, а именно вызов функции) и "statement" (например if (expression) statement -- это statement), а иногда expression может быть statement'ом (например, printf("something\n");, с точкой с запятой), это называется "expression statement".

    "expression" обычно переводится как "выражение" и не вызывает трудностей. Со "statement" сложнее. Мне нравятся переводы "конструкция" ("конструкция if", "конструкция switch") или "инструкция" ("инструкция goto", "инструкция return").


    Как называть по-человечески строчки:
    if ( a > b )
      printf("something\n");

    Конструкция if с единственной инструкцией-выражением.

    А такое:

    if(condition) {
      printf("something1\n");
      printf("something2\n");
    }

    Конструкция if с составной инструкцией содержащей две инструкции-выражения.
    Ответ написан
    2 комментария
  • Почему условие if ( a == a) может не выполняться для Embedded-разработки?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    float b;
    ...
    if (b == b)

    Не выполняется тогда и только тогда, когда в b -- NaN.

    Обоснование есть в стандарте: пункт стандарта C99 6.2.6.1:4 говорит:
    Two values (other
    than NaNs) with the same object representation compare equal, but values that compare
    equal may have different object representations.
    .
    Ответ написан
    Комментировать
  • Как выделить память для строки неизвестной длины?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как это усовершенствовать?


    Из man scanf:
    An optional 'm' character. This is used with string conversions (%s, %c, %[), and relieves the caller of the need to allocate a corresponding buffer to hold the input: instead, scanf() allocates a buffer of sufficient size, and assigns the address of this buffer to the corresponding pointer argument, which should be a pointer to a char * variable (this variable does not need to be initialized before the call). The caller should subsequently free(3) this buffer when it is no longer required.

    Т.е.:
    #include <stdio.h>
    
    int main()
    {
      char *chars;
      scanf("%m[^\n]",&chars);
      printf("%s\n", chars);
    }
    Ответ написан
    Комментировать
  • Как разобраться с указателем на указатель на массив?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что происходит в данном случае
    int ** ptr = &arr;

    Происходит initialization from incompatible pointer type.

    Получается что далее ptr == arr == &arr

    == использованное в смысле "численно равно" действительно имеет место. Но типы этих трёх значений разные: int **/int[4]/int (*)[4]

    Почему нельзя получить указатель на указатель на массив в данном случае?

    Потому что, чтобы получить указатель на указатель, надо этот второй указатель иметь. Массив -- это не указатель.
    Вот так будет работать:
    #include <stdio.h>
    
    int main(void)
    {
      int arr[4] = {1, 2, 3, 4};
      int *pa = arr;
      int ** ptr = &pa;
    
      printf("%d", **ptr); // 1
      return 0;
    }
    Ответ написан
    Комментировать
  • Почему выводится некорректное значение вещественного числа?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему если считывать число как long double, то результат получается нормальным,
    input 2 => output 8.000000 (%lf)

    потому что в scanf %lf -- это не long double, а просто double. %f -- это float, а long double -- это %Lf. См. man scanf.
    float и double обычно отличаются форматом представления, поэтому если вводить число не тем форматом scanf, то и значение получится не то, что ожидалось.
    Ответ написан
    Комментировать