2015-10-09 7 views
-3

В чем разница между разным распределением указателя?Какая разница между нормальным указателем и самореляционным указателем на языке c

struct node { 
    char *name; 
    struct node *itself; 
}; 

Мой вопрос -

Почему это важно malloc структура переменнуюуказатель name? указать что-то, пока self_referential не нужно было динамически выделять.

Я имею в виду обе версии: null pointer ... так почему?

+3

Пожалуйста, разместите вопрос в этом сообщении. При этом вам нужно выделить (иногда) для символа 'char *', потому что это строка стиля C и часто не должна ссылаться на внешнюю строку. – owacoder

+1

@owacoder: 'char *' это ** ни ** строка, ** и ** a_array_! – Olaf

+0

@Olaf - Я знаю, что это ни строка, ни массив. (Я не думал, что упоминал массивы в своем комментарии. Или я?) В этом случае, однако, он используется для имени, которое, очевидно, является ** строкой **. – owacoder

ответ

1

Почему важно имя переменной указателя структуры malloc?

1. В него можно ввести ввод. Без выделения памяти вы будете писать в недействительное местоположение, вызывая UB.

2. Так что вы можете использовать его в функциях, как strlen, strcpy, strcat (исключением является strdup но также выделить память). В противном случае причина та же, что и выше.

И это неправда, что выделение памяти не требуется для struct pointer. Вам нужно будет это сделать, создавая структуры данных без фиксированного размера.

Я имею в виду оба нулевой указатель ... так почему?

Но вы не должны разыменовать null pointer, если вы так что вы получите ошибку сегментации (если повезет).

2

Оба указателя должны быть установлены в что-то. name должен либо быть установлен, чтобы указывать на строковый литерал, массив из char, либо кусок памяти, возвращенный с malloc или calloc или realloc. itself необходимо будет установить в другой экземпляр struct node. Нужно ли использовать динамическое распределение или нет, зависит от того, что вы пытаетесь сделать.

В односвязном списке указатель itself будет содержать адрес другого экземпляра struct node. Вы можете представить его как что-то вроде следующего:

+---+---+ +---+---+ +---+---+ +---+---+ 
| | |--->| | |--->| | |--->| | |---0 
+---+---+ +---+---+ +---+---+ +---+---+  
    |   |   |   |    
    |   |   |   |    
    V   V   V   V    
+---+  +---+  +---+  +---+   
|'f'|  |'b'|  |'b'|  |'b'|   
+---+  +---+  +---+  +---+ 
|'o'|  |'a'|  |'l'|  |'l'| 
+---+  +---+  +---+  +---+ 
|'o'|  |'r'|  |'e'|  |'u'| 
+---+  +---+  +---+  +---+ 
| 0 |  | 0 |  |'t'|  |'r'| 
+---+  +---+  +---+  +---+ 
          |'c'|  |'g'| 
          +---+  +---+ 
          |'h'|  |'a'| 
          +---+  +---+ 
          | 0 |  | 0 | 
          +---+  +---+ 

У нас есть 4 экземпляра struct node. Элементы name из четырех из них указывают на строки, а члены 0 из 3 из них указывают на другие экземпляры struct node.

Теперь, независимо от того, динамически выделены ли строки или другие экземпляры узлов или нет, зависит от вашей программы.Можно выделить массив struct node и иметь каждый элемент явно указывает на следующий по очереди:

struct node nodes[N] = {{NULL, NULL}}; 

for (size_t i = 0; i < N-1; i++) 
    nodes[i].itself = &node[i+1]; 

Вы можете установить каждый узел, чтобы указать на уже существующем массиве char или строкового литерала:

char buffer[] = "foo"; 
node[i].name = buffer; 
node[j].name = "blah"; 

в качестве альтернативы, вы можете выделить все динамически:

/** 
* Adds a name to the head of a list 
*/ 
void pushName(struct node **head, const char *name) 
{ 
    struct node *newNode = malloc(sizeof *newNode); 
    if (newNode) 
    { 
    newNode->name = malloc(strlen(name) + 1); 
    if (newNode->name) 
     strcpy(newNode->name, name); 
    newNode->itself = *head; 
    *head = newNode; 
    } 
} 
... 
struct node *list = NULL; 
pushName(&list, "blurga"); 
pushName(&list, "bletch"); 
pushName(&list, "bar"); 
pushName(&list, "foo"); 

, который дает нам что-то вроде приведенной выше схеме.

Все зависит от того, что вы собираетесь делать.

+0

Спасибо ... Было полезно .. –