Как работать с указателем на указатель на структуру? - PullRequest
0 голосов
/ 06 февраля 2011

У меня есть небольшая проблема. Я только начинаю с C (из C # фона) и у меня проблемы с двойными указателями.

У меня есть следующая структура:

#ifndef __PROCESSINFO_H
#define __PROCESSINFO_H

struct ProcessInfo
{
   int ProcesId;
   int Priority;
   int ExecutionTime;
   int EllapsedTime;
   char* ProcessName;
}; 

struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime);
void ProcessInfo_ToString(struct ProcessInfo *processInfo);
void ProcessInfo_Dispose(struct ProcessInfo *processInfo);

#endif

Реализация:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "processinfo.h"

struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime)
{
    struct ProcessInfo *processInfo;
    processInfo = (struct ProcessInfo *)malloc(sizeof(struct ProcessInfo));
    processInfo->ProcessId = processId;
    processInfo->ProcessName = processName;
    processInfo->Priority = priority;
    processInfo->ExecutionTime = executionTime;
    processInfo->EllapsedTime = 0;

    return processInfo;
}

void ProcessInfo_ToString(struct ProcessInfo *processInfo)
{
    printf(" %6i %6i %10i %10i, %25s", processInfo->ProcessId, processInfo->Priority, processInfo->ExecutionTime, processInfo->EllapsedTime, processInfo->ProcessName); 
}

void ProcessInfo_Dispose(struct ProcessInfo *processInfo)
{
    if(processInfo != NULL)
    {
        if(processInfo->ProcessName != NULL)
        {
            free(processInfo->ProcessName);
        }

        free(processInfo);
    }
}

так что теперь мне нужно управлять целым рядом экземпляров ProcessInfo. Я написал другую структуру, в которой содержался бы указатель на указатель на структуру ProcessInfo, потому что я думал, что могу увеличивать и уменьшать ее по мере необходимости (без особых хлопот);

#ifndef __SCHEDULER_H
#define __SCHEDULER_H

struct Scheduler
{
    struct ProcessInfo** Processes;
};

struct Scheduler* Scheduler_Allocate(void);

#endif

Итак, вопрос в том, как инициализировать элемент ** Processes внутри метода Scheduler_Allocate? Как мне добавить к этому материал?

Ответы [ 5 ]

1 голос
/ 06 февраля 2011
size_t size = 10;//or what ever is the number of processes
struct ProcessInfo * process = (struct ProcessInfo *)malloc(size * sizeof(struct ProcessInfo));
if(!process)
    //perhaps stop program? Do something
Processes = &process;
//later on
int i;
for(i = 0; i < size; i++)
{
   printf("Process id =%d",Processes[i]->ProcesId);
   etc
}
1 голос
/ 06 февраля 2011
struct Scheduler s;
s.Processes = malloc(sizeof(struct ProcessInfo*) * size);
s.Processes[0] = ProcessInfo_Allocate(...);

// Add more items:
s.Processes = realloc(malloc(sizeof(struct ProcessInfo*) * (size + 1));
s.Processes[size] = ProcessInfo_Allocate(...);
size++;

Также см. Мой пример здесь:

Массив структур C

1 голос
/ 06 февраля 2011

Вам не нужен двойной указатель для увеличения / уменьшения размера. Просто используйте обычный указатель и realloc.

struct ProcessInfo* processes = malloc(sizeof(struct ProcessInfo) * 2);
struct ProcessInfo* processes_tmp;

if (!processes) {
   /* bail */
}

/* do whatever with processes[0] and [1] */

processes_tmp = processes;
processes = realloc(processes, sizeof(struct ProcessInfo) * 5);
if (!processes) {
    free(processes_tmp);
    /* bail */
}

/* processes[0] and [1] are unchanged, and [2] [3] and [4] are now valid */

Тогда вместо ProcessInfo_Allocate вы можете создать ProcessInfo_Init, который будет выполнять большую часть того же, за исключением выделения памяти:

int ProcessInfo_Init(struct ProcessInfo *pi, int processId, char *processName, int priority, int executionTime)
{
    if (!pi) {
        return -1;
    }
    pi->ProcessId = processId;
    pi->ProcessName = processName;
    pi->Priority = priority;
    pi->ExecutionTime = executionTime;
    pi->EllapsedTime = 0;

    return 0;
}
0 голосов
/ 06 февраля 2011

Сначала измените ваше определение на:

typedef struct Scheduler {
    struct ProcessInfo** Processes;
} Scheduler;

Затем что-то вроде этого:

Scheduler *s;
s = malloc(sizeof(Scheduler));
if (s == NULL) {
  exit(-1);
}
s = memset(s, 0, sizeof(Scheduler));
/* Or enter your own memory allocation stuff here */
i = 0; /* Or use some other number */
s->Processes[i] = someProcessInfo;
0 голосов
/ 06 февраля 2011

Указатель на указатель инициализируется как массив указателей. Так что звоните malloc(count * sizeof(ProcessInfo*)), чтобы инициализировать его. Таким образом, вы получите массив указателей на ProcessInfo. Затем многократно вызывайте malloc(sizeof(ProcessInfo)) для создания конкретных ProcessInfo структур и помещайте на них указатели на массив.

Кроме того, user470379 прав, что вам не нужен указатель на указатель, просто чтобы изменить количество элементов в вашем массиве. Но ваша идея на самом деле тоже неплохая, вы можете остаться с ней, если хотите.

Кроме того, поскольку вы знакомы с C #, я бы порекомендовал вам начать с написания чего-то вроде ArrayList на C. Затем вы можете использовать его во многих ситуациях (например, в этой).

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