Запустить структуру и распечатать все значения? - PullRequest
1 голос
/ 20 мая 2011

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

Что я делаю не так?

fn (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{

    /*
     assume that all struct members are int types

     typedef    struct 
     {
     mach_msg_bits_t    msgh_bits;
     mach_msg_size_t    msgh_size;
     mach_port_t        msgh_remote_port;
     mach_port_t        msgh_local_port;
     mach_msg_size_t    msgh_reserved;
     mach_msg_id_t      msgh_id;
     } mach_msg_header_t;

     size of the struct is 24.
     */

    printf("ID: %d \n",InHeadP->msgh_id); //prints 'ID: 1337'
    printf("Ptr: %p\n",InHeadP);

    for (int i = 0; i <= 24; i++)
    {
        int deref = *((int*)(InHeadP+i));
        printf("InHeadP[%d]=%d\n",i,deref);
            //no sign of 1337 anywhere

    }
}

P.S. Я знаю, что не должен этого делать, но это только для целей тестирования.

Ответы [ 5 ]

5 голосов
/ 20 мая 2011

Поскольку InHeadP является mach_msg_header_t*, добавление к нему целого числа фактически добавит это целое число раз sizeof(mach_msg_header_t), как если бы вы индексировали массив mach_msg_header_t с (и именно так работает индексация массива). Вам нужно привести InHeadP к int* , прежде чем выполнит арифметику, и даже тогда, когда структура имеет шесть полей, i должно идти только до 6, а не 24.

3 голосов
/ 21 мая 2011

Предпочтительным методом итерации по структуре является создание функции, которая возвращает значение или адрес поля с заданным индексом.Обратите внимание, что если порядок элементов в структуре изменяется, эта функция также должна измениться:

int * Index_Of(unsigned int index, mach_msg_header_t * p_struct)
{
    switch (index)
    {
        case 0:  return (int *) &(p_struct->msgh_bits);
        case 1:  return (int *) &(p_struct->msgh_size);
        case 2:  return (int *) &(p_struct->msgh_remote_port);
        case 3:  return (int *) &(p_struct->msgh_local_port);
        case 4:  return (int *) &(p_struct->msgh_reserved);
        case 5:  return (int *) &(p_struct->msgh_id);
    }
    return 0;
}

Просто помните, что рассматривать структуру как смежные поля (члены) не рекомендуется, так каккомпилятору разрешено добавлять отступы между элементами структуры.Таким образом, любой метод доступа к полям, кроме имени, опасен и приведет к очень сложным ошибкам.

Кстати, обрабатывать каждое поле как int также опасно.Если какой-либо из типов будет изменен на что-то другое, например double, ваш код сломается.Компилятор не поймает ошибку, потому что приведение говорит компилятору, что ВЫ знаете, что делаете.

Вы можете «перевернуть картинку» и реализовать шаблон Visitor :

struct Visitor_Void
{
    void (*fn_msgh_bits)(mach_msg_bits_t);
    void (*fn_msgh_size)(mach_msg_size_t);
    void (*fn_msgh_remote_port)(mach_port_t);
    void (*fn_msgh_local_port)(mach_port_t);
    void (*fn_msgh_reserved)(mach_msg_size_t);
    void (*fn_msgh_id)(mach_msg_id_t);
};


void Visit_Members(mach_msg_header_t * p_header,
                   struct Visitor_Void * p_visitor)
{
    (p_visitor->fn_msgh_bits)(p_header->msgh_bits);
    (p_visitor->fn_msgh_size)(p_header->msgh_size);
    (p_visitor->fn_msgh_remote_port)(p_header->msgh_remote_port);
    (p_visitor->fn_msgh_local_port)(p_header->msgh_local_port);
    (p_visitor->fn_msgh_reserved)(p_header->msgh_reserved);
    (p_visitor->fn_msgh_id)(p_header->msgh_id);
    return;
}
1 голос
/ 20 мая 2011

Нет, вы не должны этого делать!

Что здесь особенно неправильно

for (int i = 0; i <= 24; i++)
{
    int deref = *((int*)(InHeadP+i));
    printf("InHeadP[%d]=%d\n",i,deref);
}

в том, что вы печатаете первый int из 24 различных структур.

0 голосов
/ 20 мая 2011

Подождите секунду, это неправильно:

 int deref = *((int*)(InHeadP+i));

Вы хотите

int deref == *((int*)InHeadP+i)

Вы пропускаете 24 байта каждый раз через цикл, а не 4.

0 голосов
/ 20 мая 2011

Когда вы вызываете (int *) (InHeadP + i), вы выполняете арифметику указателя для mach_msg_header_t, который имеет размер 24. Итак, ваша первая итерация находится в начале структуры, а вторая - сразу после вашей структуры.Вы обращаетесь к какой-либо другой памяти.

Попробуйте (((int *) InHeadP) + i).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...