C: Структуры и массив - необходим обзор и помощь - PullRequest
1 голос
/ 10 января 2010

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
    char name[10];
} man;

int main (int argc, const char * argv[]) {
    int i;
    man john;
    strcpy(john.name, "john");

    // array of structures
    man men[10];
    strcpy(men[3].name, "john");
    printf("*** %s ***\n", men[3].name);

    // dynamic array of structures
    man *men2;
    men2 = malloc(10 * sizeof(man));
    strcpy(men2[3].name, "john");
    printf("*** %s ***\n", men2[3].name);

    // multidimensional array of structures
    man men3[10][10];
    strcpy(men3[3][3].name, "john");
    printf("*** %s ***\n", men3[3][3].name);

    // dynamic multidimensional array of structures
    man **men4;
    men4 = malloc(10 * sizeof(man*));
    for (i = 0; i < 10; i++)
        men4[i] = malloc(10 * sizeof(man*));
    strcpy(men4[3][3].name, "john");
    printf("*** %s ***\n", men4[3][3].name);

    // array of pointer to structure
    man *men5[10];
    men5[3] = &john;
    printf("*** %s ***\n", men5[3]->name);

    // dynamic array of pointers to structure
    man **men6;
    men6 = malloc(10 * sizeof(*men6));
    men6[3] = &john;
    printf("*** %s ***\n", men6[3]->name);  

    // dynamic multidimensional array of pointers to structures
    /* ? */

    return 0;
}

Можете ли вы:

  1. скажи мне, если все правильно
  2. объясните, почему у мужчин4 я использую sizeof(man*), но у мужчин6 это sizeof(*men6) (звездочка)
  3. объяснить, как создать динамический многомерный массив указателей на структуры (последняя точка)
  4. объясните мне men4? это работает, но мне кажется, что это скорее массив указателей на структуру, чем многомерный массив структур!

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 10 января 2010
  • 2: Это два примера, которые делают одно и то же: sizeof(*men6) == sizeof(man*)!
  • 3: То же, что и в примере с men5, но многомерный.
  • 4: пример men4 не совсем корректен. Насколько я понимаю, что это должно означать, этот пример должен выглядеть так:

man ***men4; // 10x10 multidimensional
men4 = malloc(10 * sizeof(man**));
for (i = 0; i < 10; i++)
{
    men4[i] = malloc(10 * sizeof(man*));
    for(j = 0; j < 10; ++j)
        men4[i][j] = malloc(sizeof(man));
}    
strcpy(men4[3][3]->name, "john");
printf("*** %s ***\n", men4[3][3]->name);
1 голос
/ 10 января 2010

Во-первых, ваши эти два случая

// dynamic multidimensional array of structures
man **men4;
men4 = malloc(10 * sizeof(man*));
for (i = 0; i < 10; i++)
    men4[i] = malloc(10 * sizeof(man*));

и

// dynamic array of pointers to structure
man **men6;
men6 = malloc(10 * sizeof(*men6));
men6[3] = &john;
printf("*** %s ***\n", men6[3]->name);

концептуально одинаковы. В обоих случаях у вас есть указатель на указатель на man. Вы используете эти указатели по-разному. Также первый имеет ошибку. Вместо:

    men4[i] = malloc(10 * sizeof(man*));

Вы должны были написать:

    men4[i] = malloc(10 * sizeof(man));

потому что каждый men4[i] имеет тип "указатель на man". Именно из-за этой ошибки я обычно предпочитаю, чтобы мои звонки malloc() имели вид:

a = malloc(N * sizeof *a);

Итак, ваш звонок стал бы:

men4[i] = malloc(10 * sizeof *men4[i]);

Это менее подвержено ошибкам.

Итак, ответ на ваш вопрос (2) заключается в том, что вы должны использовать sizeof(man *) только при выделении для men4, но не внутри цикла. (Или, теперь вы знаете лучший способ для вызова malloc(), так что цикл за пределами вызова становится men4 = malloc(10 * sizeof *men4);.)

  1. Все правильно, за исключением вызова malloc(), как указано выше.
  2. См. Выше.
  3. Вы хотите структурировать массив указателей. Чтобы получить массив, вам нужно [], так как это указатель на нужный вам указатель (многомерный), вам нужно два **. Таким образом, вы получаете: man **(men7[10]);, но поскольку [] связывается более плотно, чем *, вы можете записать его как man **men7[10];.
  4. men4 не является многомерным массивом или массивом указателей. Это указатель на указатель на man. Когда вы выделяете память для men4, вы выделяете пространство для 10 указателей на man. Затем каждому указателю выделяется место для 10 man. Тот факт, что вы можете индексировать men4 как многомерный массив, является результатом такого распределения. В вашем цикле каждому men4[i] могло бы быть выделено пространство для различного числа man значений, если вам это нравится, что невозможно сделать с многомерными массивами.

Указатели не являются массивами. Массивы не указатели. Пожалуйста, прочитайте все вопросы и ответы в разделе 6 FAQ C для подробностей.

0 голосов
/ 10 января 2010
  1. Семантически правильно
  2. Это IS массив указателей, поэтому вам нужно выделить элементы размером с указатель, а размер указателя равен sizeof(void*), что равно sizeof(man*)
  3. man ***men;
  4. Да, это так. Должно быть man **men[10];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...