2017-02-04 14 views
0

Вот часть кода, которая меня сбивает с толку.Объявление типа C (без пробела) (двоичное дерево, примерный)

struct tNode { 
    int key;   // search key for this item 
    int data;   // data for this item 
    struct tNode *left, *right; // children 
}; 

typedef struct tNode tree_type; 

/**************** tree_new() ****************/ 
/* Create a new tree */ 
tree_type * 
tree_new(const int key, const int data) 
{ 
    tree_type *node = malloc(sizeof(struct tNode)); 

    ... 
    } 
} 

Так что я не совсем получаю синтаксис tree_type * прямо над tree_new функции. Не похоже на указатель ... не уверен, что он там делает.

--------------------- post-edit Спасибо всем, кто помог!

+0

Это указатель. 'tree_new' возвращает указатель-to -tree_type'. – jtbandes

+0

Это возвращаемый тип функции. Это указатель в порядке ... –

+3

Разрывы строк не являются специальными в C. Это так же, как вы написали 'tree_type * tree_new (...' в одной строке. – user2357112

ответ

3

Вы должны прочитать обе линии вместе:

tree_type * 
tree_new(const int key, const int data) 

это просто еще один легальный способ записать определение функции с типом возвращаемого значения:

tree_type *tree_new(const int key, const int data) 

, поскольку она не заканчивается точкой с запятой , утверждение продолжается на следующей строке.

3

tree_type * не является пустой декларацией. tree_type является спецификатором декларации и * является частью декларатора для функции tree_new (Благодаря @Jonathan Leffler для nitpick).
Что говорит, tree_type * изображает тип возврата функции tree_new.

+1

Строго строго,' tree_type' является _declaration_specifier_ и '*' является частью _declarator_ для этой функции. Но это самый ничтожный выбор. –

+0

@JonathanLeffler; На самом деле это правильно в соответствии с языковой грамматикой. – haccks

1

Ваше использование указателей выглядит отлично. Ваш malloc() возвращает указатель на память на определенный тип указателя. Осмотрев свой небольшой код, я думал, что вы могли бы принести пользу с предложениями для него и контекста вашего двоичного пример дерева может быть использован в.

ЬурейеГо nameing конвенция

Struct декларация и ЬурейиЙ может быть сделаны в том же время. Это вопрос предпочтения. Общим соглашением для typedefs в C является его имя в форме someType_t, чтобы иметь последовательный способ идентификации typedefs везде, где они используются.

обнуления распределяемой памяти

Я обычно использую calloc(), а не malloc(), потому что в отличие от malloc(), calloc() нули выделенной памяти.

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

безопасного распределение и контроль за ошибки выделения

Распределение делает нулевую проверку и отображает явный простой вне памяти сообщений, если не хватает памяти. Если в программе нет памяти, что обычно считается фатальным и оправданием выхода из программы, потому что, если в любом месте недостаточно памяти, все может повредиться повсюду. Это была бы очень редкая программа, которая бы изощренно справлялась с избыточным состоянием памяти, например, чтобы ее можно было ждать и повторять до тех пор, пока память не будет доступна снова, поэтому простое выключение является обычным явлением.Использование безопасных функций распределения сэкономит вам много нулевой проверки в вызывающем уровне.

Установка освободила указатели на NULL

Примечания установки освобожденного указателя на NULL. Если это делается последовательно, то указатель всегда можно определить как действительный или нет с помощью проверки NULL. Кроме того, освобождение NULL в большинстве систем - это NOP, поэтому вы можете снизить риск двойного освобождения (освобождение указателя более одного раза), что может привести к катастрофическим и трудным для диагностики ошибок, особенно в более крупных программах.

Простой пример двоичного дерева
(компилирует/работает)

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

typedef struct Tree { 
    int key;    
    int data;   
    struct Tree *left, *right; 
} tree_t; 

// Dummy data just for example: 

#define KEY 1 
#define VAL 2 
#define KEY2 3 
#define VAL2 4 
#define KEY3 5 
#define VAL3 6 

tree_t *node_create_safe(const int, const int); 
void free_tree(tree_t *); 

int 
main() { 
    tree_t *rootNode = node_create_safe(KEY, VAL); 
    rootNode->left = node_create_safe(KEY2, VAL2);; 
    rootNode->right = node_create_safe(KEY3, VAL3);; 
    free_tree(rootNode); 
    rootNode = NULL;  
} 

/* 
* node_create_safe() - allocates node, always returns pointer. 
* 
*  Side effects: Terminates program on allocation failure. 
*/ 
tree_t * 
node_create_safe(const int key, const int data) { 
    tree_t *node = calloc(sizeof(struct Tree), 1); 
    if (node == NULL) { 
     fprintf(stderr, "out of memory\n"); 
     exit(-1); 
    } 
    node->key = key; 
    node->data = data; 
    return node; 
} 

/* 
* free_tree() - Recursively frees [sub]tree 
*/ 
void 
free_tree(tree_t *node) { 
    if (node->left != NULL) 
     free_tree(node->left); 
    if (node->right != NULL) 
     free_tree(node->right); 
    free(node); 
} 
2
int *foobar(int x) { 
    return 42; 
} 

такая же, как

int * 
foobar(int x) 
{ 
    return 42; 
} 

То же самое с tree_type (или struct tNode).

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

  • Нет связанных вопросов^_^