Ответы пользователя по тегу C
  • Как создать указатель на функцию main?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    int main(void)
    {
        int (*pmain)(void) = main;
    }


    например int* func;

    Это указатель на int, а не на функцию.
    Ответ написан
  • Почему код именно так работает?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Символы повторяются из-за static?

    Не из-за static, а из-за того, что _itoa всегда возвращает один и тот же адрес. Попробуй так, зацени разницу:
    char *_itoa(int i) {
      static int slot;
      static char buf[10][2];
      slot = (slot + 1) % 10;
      buf[slot][0] = i + '0';
      buf[slot][1] = '\0';
      return buf[slot];
    }
    
    int main() {
    
      printf("%s + %s = %s", _itoa(2), _itoa(2), itoa(4));
      _getch();
    }
    Ответ написан
  • Почему не срабатывает шеллкод?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    при компиляции флаг из реестра не удаляется. В чем может быть проблема?

    В том, что ты засунул бинарный код в параметр функции, в котором должна быть строка с именем программы для запуска и её параметрами. Непонятно, почему ты ожидаешь, что WinExec бросится выполнять машинный код в этой строке. WinExec имеет код возврата, который недвусмысленно тебе сказал бы в чём ошибка (путь или файл для запуска не найдены), если бы ты его проверил.
    И, кстати, байт с кодом 0 по смещению 0x246 -- это тоже часть шелл-кода, терминатор командной строки.

    Байты из зеленой области, как я понял, это информация линкера golink. Так ли это?

    Это заголовок файла формата PE. Да, его туда записал линкер. Нет, это не информация линкера, это информация в основном для загрузчика ОС, а так же для дизассемблера и прочих binutils.
    Ответ написан
  • Как вывести элементы матрицы, которые находятся ниже главной диагонали?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    int **matrix = (int**)malloc(matrix_size * sizeof(int));

    Должно стать
    int **matrix = (int**)malloc(matrix_size * sizeof(int *));

    потому что ты выделяешь массив указателей, а не массив целых чисел, а sizeof(int) вполне может быть не равно sizeof(int *).

    for (int i = 0; i < matrix_size; ++i)
        {
            for (int j = 0; j < matrix_size; ++j)
            {
                if(i > j)
                {
                    arr[i] = matrix[i][j];
                }
            }
        }


    Должно стать
    counter = 0;
        for (int i = 0; i < matrix_size; ++i)
        {
            for (int j = 0; j < matrix_size; ++j)
            {
                if(i > j)
                {
                    arr[counter++] = matrix[i][j];
                }
            }
        }


    потому что иначе все элементы находящиеся в одной строке matrix ты складываешь в один и тот же элемент массива arr.
    Ответ написан
  • Сколько будут занимать места параметры в данном случае?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    ума не приложу, почему размер void _stdcall foo(short a, short b); параметров равен 8

    Потому что аргументы размером меньше 4 байт расширяются до 4 байт. См.

    Как выяснилось, стек растет не только на 4 байта, а на 2.

    То, что в стек физически можно положить 2 байта (а можно ведь и 1, и 3 -- sub $imm, %esp) не означает, что это следует делать. См:
    The stack will always be maintained 16-byte aligned, except within
    the prolog (for example, after the return address is pushed), and except where
    indicated in Function Types for a certain class of frame functions
    Для венды на x86 я такого описания на том же сайте не нашёл, но точно выравнивание должно быть не меньше 4.
    Ответ написан
  • Зачем нужно выравнивание памяти по слову?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Я не знаю, можно ли такого уровня детали найти для современных процессоров, а вот для i80386 в спецификации, в разделе 5.3.6 легко можно видеть, что невыравненный доступ к памяти занимает два цикла, вместо одного.
    За пределами мира x86 многие процессоры вообще не поддерживают доступ к невыравненным данным на аппаратном уровне.
    Ответ написан
  • Какой тип данных будет более правильным?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    есть ли смысл использовать простые чар массивы формата char name[32] или динамические массивы char name[] в замену указателям с последующим выделением им памяти?

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Сразу скажу, комп у меня слабенький и ждать 3-4 часа чтоб понять что забыл в конце оператора точку с запятой поставить, это не хорошо?!

    При разработке необязательно использовать конфигурацию ядра со всеми включёнными опциями. Типичный конфиг который я использую при разработке собирается с нуля за 2 минуты.
    Кроме того, ядерный Makefile понимает цели вида *.o. Т.е. можно взять и откомпилировать один файл из дерева исходников ядра. Например: make init/main.o.
    Если ты меняешь что-то в исходниках, перекомпилироваться будет только то, что действительно зависит от того, что ты поменял. Поменяешь .c -- перекомпилируется единственный соответствующий ему файл .o.

    как можно тестировать компоненты ядра

    Это совсем другой вопрос. Под просто тестированием понимают проверку того, что код работает правильно, а не то, что он собрался.
    Ответ написан
  • Error loading uncompressed kernel without PVH ELF Note ( osdev ) !?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    пытаюсь понять, почему qemu не хочет запускать ядро....


    Потому что это не заголовок multiboot, MAGIC тут взят из старой версии формата, а структура -- из версии 2:

    MAGIC equ 0x1BADB002
    ...
    grubBoot:
      dd MAGIC
      dd FLAGS
    ;	dd 0
      dd (end_grubBoot - grubBoot)
      dd -(MAGIC + FLAGS + (end_grubBoot - grubBoot))
    ;	dd -(MAGIC + 0 + (end_grubBoot - grubBoot))
      
    ;	dw 0
    ;	dw FLAGS
    ;	dd 8
    end_grubBoot:


    QEMU отлично понимает заголовок старого формата:

    MAGIC equ 0x1BADB002
    
      dd MAGIC
      dd FLAGS
      dd -(MAGIC + FLAGS)


    И с этим изменением твой код прекрасно загружается и выполняется:

    trace
    ...
    
    Trace 0: 0x7f2a71e084c0 [00000000/000caa1a/0xb0]
    ----------------
    IN:
    0x00102060:  9b                       wait
    0x00102061:  db e3                    fninit
    0x00102063:  bc 44 23 10 00           movl     $0x102344, %esp
    0x00102068:  53                       pushl    %ebx
    0x00102069:  50                       pushl    %eax
    0x0010206a:  e8 68 00 00 00           calll    0x1020d7
    
    Trace 0: 0x7f2a71e08800 [00000000/00102060/0xb0]
    ----------------
    IN:
    0x001020d7:  55                       pushl    %ebp
    0x001020d8:  89 e5                    movl     %esp, %ebp
    0x001020da:  68 00 10 10 00           pushl    $0x101000
    0x001020df:  e8 8d ff ff ff           calll    0x102071
    
    Linking TBs 0x7f2a71e08800 [00102060] index 0 -> 0x7f2a71e08a40 [001020d7]
    Trace 0: 0x7f2a71e08a40 [00000000/001020d7/0xb0]
    ----------------
    IN:
    0x00102071:  55                       pushl    %ebp
    0x00102072:  89 e5                    movl     %esp, %ebp
    0x00102074:  53                       pushl    %ebx
    0x00102075:  83 ec 10                 subl     $0x10, %esp
    0x00102078:  c7 45 f4 00 80 0b 00     movl     $0xb8000, -0xc(%ebp)
    0x0010207f:  c7 45 f8 00 00 00 00     movl     $0, -8(%ebp)
    0x00102086:  eb 35                    jmp      0x1020bd
    
    Linking TBs 0x7f2a71e08a40 [001020d7] index 0 -> 0x7f2a71e08c80 [00102071]
    Trace 0: 0x7f2a71e08c80 [00000000/00102071/0xb0]
    ----------------
    IN:
    0x001020bd:  8b 55 f8                 movl     -8(%ebp), %edx
    0x001020c0:  8b 45 08                 movl     8(%ebp), %eax
    0x001020c3:  01 d0                    addl     %edx, %eax
    0x001020c5:  0f b6 00                 movzbl   (%eax), %eax
    0x001020c8:  0f be c0                 movsbl   %al, %eax
    0x001020cb:  3b 45 f8                 cmpl     -8(%ebp), %eax
    0x001020ce:  7f b8                    jg       0x102088
    
    Linking TBs 0x7f2a71e08c80 [00102071] index 0 -> 0x7f2a71e08f00 [001020bd]
    Trace 0: 0x7f2a71e08f00 [00000000/001020bd/0xb0]
    ----------------
    IN:
    0x00102088:  8b 45 f8                 movl     -8(%ebp), %eax
    0x0010208b:  8d 14 00                 leal     (%eax, %eax), %edx
    0x0010208e:  8b 45 f4                 movl     -0xc(%ebp), %eax
    0x00102091:  01 d0                    addl     %edx, %eax
    0x00102093:  8b 55 f8                 movl     -8(%ebp), %edx
    0x00102096:  8d 0c 12                 leal     (%edx, %edx), %ecx
    0x00102099:  8b 55 f4                 movl     -0xc(%ebp), %edx
    0x0010209c:  01 ca                    addl     %ecx, %edx
    0x0010209e:  0f b7 12                 movzwl   (%edx), %edx
    0x001020a1:  89 d3                    movl     %edx, %ebx
    0x001020a3:  b3 00                    movb     $0, %bl
    0x001020a5:  8b 4d f8                 movl     -8(%ebp), %ecx
    0x001020a8:  8b 55 08                 movl     8(%ebp), %edx
    0x001020ab:  01 ca                    addl     %ecx, %edx
    0x001020ad:  0f b6 12                 movzbl   (%edx), %edx
    0x001020b0:  66 0f be d2              movsbw   %dl, %dx
    0x001020b4:  09 da                    orl      %ebx, %edx
    0x001020b6:  66 89 10                 movw     %dx, (%eax)
    0x001020b9:  83 45 f8 01              addl     $1, -8(%ebp)
    0x001020bd:  8b 55 f8                 movl     -8(%ebp), %edx
    0x001020c0:  8b 45 08                 movl     8(%ebp), %eax
    0x001020c3:  01 d0                    addl     %edx, %eax
    0x001020c5:  0f b6 00                 movzbl   (%eax), %eax
    0x001020c8:  0f be c0                 movsbl   %al, %eax
    0x001020cb:  3b 45 f8                 cmpl     -8(%ebp), %eax
    0x001020ce:  7f b8                    jg       0x102088
    
    Linking TBs 0x7f2a71e08f00 [001020bd] index 1 -> 0x7f2a71e091c0 [00102088]
    Trace 0: 0x7f2a71e091c0 [00000000/00102088/0xb0]
    Linking TBs 0x7f2a71e091c0 [00102088] index 1 -> 0x7f2a71e091c0 [00102088]
    Trace 0: 0x7f2a71e091c0 [00000000/00102088/0xb0]
    ----------------
    IN:
    0x001020d0:  90                       nop
    0x001020d1:  83 c4 10                 addl     $0x10, %esp
    0x001020d4:  5b                       popl     %ebx
    0x001020d5:  5d                       popl     %ebp
    0x001020d6:  c3                       retl
    
    Linking TBs 0x7f2a71e091c0 [00102088] index 0 -> 0x7f2a71e098c0 [001020d0]
    Trace 0: 0x7f2a71e098c0 [00000000/001020d0/0xb0]
    ----------------
    IN:
    0x001020e4:  83 c4 04                 addl     $4, %esp
    0x001020e7:  eb fe                    jmp      0x1020e7
    
    Trace 0: 0x7f2a71e09b00 [00000000/001020e4/0xb0]
    ----------------
    IN:
    0x001020e7:  eb fe                    jmp      0x1020e7
    
    Linking TBs 0x7f2a71e09b00 [001020e4] index 0 -> 0x7f2a71e09c40 [001020e7]
    Trace 0: 0x7f2a71e09c40 [00000000/001020e7/0xb0]
    Linking TBs 0x7f2a71e09c40 [001020e7] index 0 -> 0x7f2a71e09c40 [001020e7]
    
    ...


    Ещё непонятно, зачем такие игры с форматом kernel, можно было же напрямую:
    LDEMU=-melf_i386
    kernel: $(CSOURCES) $(NASMSOURCES) $(LDFILE)
            $(CC) $(CEMU) -std=c$(CSTD) -c $(CSOURCES) -ffreestanding -nostdlib -nostdinc -fno-pic
            $(ASM) $(NASMSOURCES)
            $(LD) $(LDEMU) --nmagic -T$(LDFILE) -o kernel *.o
    Ответ написан
  • Как отсортировать матрицу?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Мне нужна хотя бы идея как это можно реализовать

    Это можно реализовать функцией qsort. Матрицу хранить по столбцам а не по строкам.
    Ответ написан
  • Как работать с комплексными числами в си?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    VS пишет...

    в С89 нет complex.h, он появился в C99. VS не поддерживает С99. Следовательно complex.h который у тебя есть -- нестандартный. Надо смотреть в него, чтобы понять, как его использовать.
    (Подозреваю, что надо выкинуть слово double из определений переменных).
    Ответ написан
  • Почему в программе утечка памяти?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Укажите на ошибки в коде

    Можно собрать программу с -g, и valgrind сам тебе укажет с точностью до строчки в исходниках, где была выделена утёкшая память.

    как мне вводить строку с неизвестной длинной?

    char *str = NULL;
    scanf("%m[^\n]", &str);
    Ответ написан
  • Почему рекурсия вовремя не останавливается?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    При компиляции выдает ошибку

    А на скрине -- отладчик не может найти исходник для функции strcat. Т.е. всё с компиляцией нормально.

    struct SYM* buildTree(struct SYM *psym[], int N)
    ...
    
    void division(struct alphabet *alphabetLetter, int groupCount)
    {
      int psysms[256];
    ...
      psysms[i] = &alphabetLetter[i];
    ...
      struct SYM *root = buildTree(psysms, alphabetLen);
    ...
    }


    Тут происходит что-то фееричное с типами: сначала указатели записываются в массив int, потом этот массив передаётся в buildTree который ожидает совсем другое.
    Ответ написан
  • Почему поле fd в событии epoll_event не задано?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    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 -- вполне нормальный файловый дескриптор.
    Короче, я попробовал, у меня работает. Если у тебя не работает -- приведи весь код.
    Ответ написан
  • Си. Что означает данное высказываение?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Желательно привести наглядный пример.


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

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

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    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);
    }
    Ответ написан
  • Почему неправильно преобразуется структура?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Из за чего это ?

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

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Как на Си вывести флаги в том же формате, что делает команда 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
    http://dilbert.com/strip/1998-08-24
    while (size <=0)//проверка ввода
            goto check;//в случае неудачи, переход по метке check на 40 строку

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


    goto mark;

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24

    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";
        }
      }
    }
    Ответ написан