Указатель на массив структур и получение памяти - PullRequest
4 голосов
/ 15 апреля 2009

A link - указатель на узел

typedef struct node * link;

В main () у меня есть следующий код (config-> m это просто целое число):

// array of pointers to structs
link heads[config->m]; 

// make memory for head nodes
for(i = 0; i < config->m; i++)
  heads[i] = malloc(sizeof(struct node));

Код работает (что здорово). Но есть ли способ, которым я могу выделить config->m частей памяти без цикла? Я пытался

link heads[config->m];
heads = malloc(sizeof(struct node) * config->m);

но мой дружественный компилятор соседей говорит мне incompatible types in assignment

Я знаю, что мог бы использовать

struct node heads[config->m];

Но я хочу сделать это с помощью указателей.

И, как всегда, кто-то спросит меня, является ли это частью домашней работы, и ответ - да (вроде). Но этот конкретный кусок кода не имеет ничего общего с фактическим назначением; это для моего собственного просветления. Но спасибо за вопрос: |

Ответы [ 2 ]

3 голосов
/ 15 апреля 2009

Нет, вам нужен цикл. Ваш массив головок по сути является двумерным массивом. Вам нужно как минимум два распределения. Первый - это массив указателей:

link * heads = (link*)malloc (config->m * sizeof (link));

Второй - это память, на которую указывает каждый элемент массива головы:

link buf = (link)malloc(sizeof(struct node) * config->m);
for(i = 0; i < config->m; i++)
    heads[i] = &buf[i];

А затем отменить выделение:

free(heads);
free(buf);
1 голос
/ 15 апреля 2009
link heads[config->m]; 
link buffer = malloc(sizeof(struct node) * config->m);

for(i = 0; i < config->m; i++)
  heads[i] = &buffer[i];

....
free(buffer);

При редактировании: На самом деле, вам не нужно heads. Во-первых, давайте избавимся от link, поскольку (см. Комментарии в ответе Cannonade) это только запутывает проблему.

Давайте представим, что узел структуры является узлом в навязчивом связанном списке и выглядит следующим образом:

      struct node {
        int val;
        int filler[10]; // this is pure filler, to make node big
        struct node* next;
      };

Теперь мы добавляем наши include и config-> m:

  #include <stdio.h>
  #include <stdlib.h>
  // your config->m
  const int m = 10 ; 

А в main () мы печатаем размер узла:

  int main() {

     printf( "sizeof( struct node ) = %i\n", sizeof( struct node) );

Теперь мы объявляем указатель на узел:

     // na is a node pointer
     struct node* na;

И malloc до м узлов. malloc возвращает адрес массива, который также является адресом первого узла в массиве. Устанавливаем на адрес, который возвратил malloc:

      na = malloc(sizeof(struct node) * m);

Теперь мы будем использовать na, указатель, как если бы это был массив. Это работает, потому что C определяет array[offset] как *(array + offset * sizeof(element))

     int i;
     // we give the first node a val of zero
     na[0].val = 0;
     // and a null next pointer
     na[0].next = 0 ;

Теперь мы пройдемся по остальной части массива и установим каждый узел рядом с PREVIOUS узлом в массиве:

     for(i = 1; i < m; i++) {
        na[i].val = i ;
        // na[ offset ] is *(na + offset)
        // we don't want to dereference, 
        // we want the address, so we use the 
        // address-of operator ("&")
        na[i].next = &na[ i - 1 ];
     }

Наша голова - последний узел в массиве na[ m - 1]. Каждый next в списке является предшествующим узлом в массиве. Опять же, мы используем оператор address-of, если нам нужен указатель, вместо того, что указано на:

     struct node* current = &na[ m - 1 ];

Мы распечатаем адрес каждого узла. Это должен быть адрес его next указателя узла + sizeof( struct node), потому что каждый узел является узлом после (в массиве) своего следующего в списке (список является массивом «полностью измененный»).

Мы приводим его к типу char *, чтобы получить результат в байтах. Если мы не разыгрываем, мы получаем результат в единицах truct node* (что всегда должно быть 1).

     while( current ) {
        printf( "val %i, address of current %p, ", current->val, current) ;
        printf( " address of current->next %p, ", current->next ) ;
        if( current->next ) {
           printf( " distance from next: ");
           printf( "in bytes %i, ", 
              ( (char*) current)  - (char*) current->next ) ;
           printf( " in struct nodes %i", current  - current->next ) ;
        }
        printf( "\n" );
        current = current->next;   
     }

     return 0;
  }

В моей системе это выдает:

  sizeof( struct node ) = 48
  val 9, address of current 0x804a1b8,  address of current->next 0x804a188,  distance from next: in bytes 48,  in struct nodes 1
  val 8, address of current 0x804a188,  address of current->next 0x804a158,  distance from next: in bytes 48,  in struct nodes 1
  val 7, address of current 0x804a158,  address of current->next 0x804a128,  distance from next: in bytes 48,  in struct nodes 1
  val 6, address of current 0x804a128,  address of current->next 0x804a0f8,  distance from next: in bytes 48,  in struct nodes 1
  val 5, address of current 0x804a0f8,  address of current->next 0x804a0c8,  distance from next: in bytes 48,  in struct nodes 1
  val 4, address of current 0x804a0c8,  address of current->next 0x804a098,  distance from next: in bytes 48,  in struct nodes 1
  val 3, address of current 0x804a098,  address of current->next 0x804a068,  distance from next: in bytes 48,  in struct nodes 1
  val 2, address of current 0x804a068,  address of current->next 0x804a038,  distance from next: in bytes 48,  in struct nodes 1
  val 1, address of current 0x804a038,  address of current->next 0x804a008,  distance from next: in bytes 48,  in struct nodes 1
  val 0, address of current 0x804a008,  address of current->next (nil),
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...