2016-03-22 2 views
0

мне дали код, чтобы построить на, и я наткнулся на несколько странных структур:Почему массив может быть объявлен в структуре таким образом и как его использовать?

typedef struct graph_t* Graph; 
typedef struct vertex_t* Vertex; 

struct vertex_t { 
    int id; 
    char *label; 

    //Implement a way to store edges... 
}; 


struct graph_t { 

    /*# vertices...*/ 
    int order; 

    /*# edges...*/ 
    int size; 

    /*Array of vertices...*/ 
    Vertex vertices; 
}; 

Вы можете, вероятно, видеть, что это способ хранения графа. Однако я смущен, так как объявлен «массив вершин»: Vertex vertices. Нет ничего, чтобы указать, что vertices на самом деле является массивом, он просто кажется единственной вершиной (что не имело бы смысла, так как граф может иметь много вершин).

Как можно объявить массив таким образом и почему это работает?

Также, как бы я начал инициализировать (?) Массив и как он будет использоваться? Точно так же, как обычный массив?

EDIT: Я забыл добавить typedefs и некоторые отсутствующие данные, кажется, что существует typedef vertex_t*, что делает это законным?

+4

Простой: это не массив. Просто потому, что комментарий говорит, что его массив не означает, что это массив. – ckruczek

+0

@ckruczek Если это так, как его можно использовать в качестве массива (как предполагал разработчик)? – JavascriptLoser

+3

Не может. Это не массив и не может использоваться как массив. – ckruczek

ответ

1

После того, как сообщение отредактировано, вы по-прежнему должны иметь malloc() блок памяти для каждого vertices и label при инициализации. Например:

Graph newGraph(size_t n, size_t labelPerVertex) 
{ 
    Graph aGraph = malloc(sizeof (struct graph_t)); 
    aGraph->vertices = malloc(sizeof (struct vertex_t) * n); // n Vertices 
    size_t i; 
    for(i = 0; i < n; i++) 
     aGraph->vertices[i].label = malloc(labelPerVertex); // array of labelPerVertex chars for every vertex 
    return aGraph; 
} 
+1

@PythonNewb Это все еще довольно плохо. проблема заключается в том, что член 'vertices' в' struct graph_t' должен быть объявлен как указатель на Vertex (то есть 'Vertex * vertices') для массива, размер которого можно установить во время выполнения, иначе он должен быть объявлен как' Ve rtex [someConstant] vertices' для массива, максимальный размер которого известен во время компиляции. – Logicrat

+0

@PythonNewb Я согласен с Logicrat. Первый предпочтительнее, потому что вы можете случайно вернуть указатель на локальную переменную в последнем случае. –

+0

@PythonNewb ответ обновлен, надеюсь, это то, что вы хотите –

0
/*Array of vertices...*/ 
Vertex vertices; 

Комментарий неверен. Это не массив. Он не может использоваться как массив Vertex, потому что он не один.

Возможно, уведомление об осуществлении будет заменено на то, что делает сам Vertex в массив вершин, но это сделало бы комментарий в лучшем случае неопределенным.

1

Существует очень плохой метод, что это может быть прологом. Это будет связано с первым распределением достаточно большого куска памяти и лить его на struct vertex_t.

Например:

size_t size = sizeof(struct vertex_t) + 1000 * sizeof(Vertex); 
struct vertex_t* memory = (struct vertex_t *) malloc(size); 
Vertex* array = &memory->vertices; 

Теперь array должны быть в состоянии принять подстрочные от [0] до [1000], не получая ошибки памяти. Но только потому, что вы можете это сделать, это не значит, что вам нужно. Это ужасная техника, и я не могу сказать об этом достаточно плохо. Не делай этого. Но это может происходить, когда идет исходный автор кода.

+1

Вне ужасного, ее также ужасно отлаживается и имеет полностью читаемость мусора. – Magisch

+0

@PythonNewb Да, ваше редактирование (которое поясняет, что 'Vertex' является typedef для' vertex_t * ', а не тип' struct' сам меняет почти все. (Код по-прежнему плохой из точки удобочитаемости, но это по крайней мере, законно.) – jamesdlin

+0

@jamesdlin Должен ли я создать новый вопрос из-за лица, что все было изменено, или я должен ждать здесь новых ответов? – JavascriptLoser

Смежные вопросы