2014-11-01 3 views
0

В Язык программирования C по KNR - 2-е издание, раздел 6.5 они определили функцию strdup таким образом:Почему они использовали функцию strdup в разделе 6.5 и?

char *strdup(char *s) 
{ 
    char *p; 

    p = (char *) malloc(strlen(s) + 1) /* +1 for the '\0' */ 
    if (p != NULL) 
    strcpy(p, s); 
    return p; 
} 

Использование необходимо скопировать строку на член структуры tnode определяется следующим образом:

struct tnode { 
char *word; 
int count; 
struct tnode *left; 
struct tnode *right; 
}; 

Вызывается, как это:

struct tnode *addtree(struct tnode *p, char *w) 
{ 
... 
p->word = strdup(w); 
... 
} 

Почему мы не можем использовать что-то подобное?

strcpy(p->word, w); 
+0

Вы должны сделать malloc(), что функция strdup делает где-то прежде, чем вы сможете использовать strcpy в переменной указателя символа. слово должно указывать на действительную память. При первом экземпляре это может указывать куда угодно. – Scooter

+0

Как вы думаете, что копирует * в *? «скопируйте строку в член структуры» - нет, это не то, что она делает ... этот член - это указатель, а не массив. –

+0

@Scooter По сути, я хотел знать причину явного распределения через malloc(). Я был (я) под впечатлением, что объявление параметра указателя также выделяет память для соответствующего типа данных. – Sohail

ответ

3

Если использовать «что-то вроде»

strcpy(p->word, w); 

тогда программа будет иметь неопределенное поведение, потому что 1) p-> Слово было не инициализированы и имеют какое-либо неопределенное значение; и 2) этот оператор пытается записать в память, которая не была выделена.

Если вы выделить память и инициализировать p-> слово с действительным адресом памяти, а затем использовать «что-то вроде»

strcpy(p->word, w); 

то на самом деле вы будете писать ту же реализацию strdup самостоятельно.

+0

Так что если бы addtree получал саму структуру вместо указателя на структуру, работало бы «что-то подобное»? – Sohail

+0

@captainsomewhere Если, например, структура будет иметь массив символов, достаточно большой, чтобы передать аргумент как строку, тогда вы могли бы просто скопировать аргумент в массив. –

+2

@ в другом месте: это * независимо * от того, находится ли 'char *' внутри структуры или нет. Это не имеет никакого отношения к самой структуре. – usr2564301

3

Прежде всего, необходимо выделить память для p->word, то вы можете использовать в качестве strcpy(p->word, w);word является char указатель и память не выделяется на него раньше.

Так что, если вы звоните strcpy(p->word, w); без выделения памяти, это приведет к Undefined behavior.

+0

Роджер. Не удается проголосовать, недостаточно репутации. Спасибо за ссылку. – Sohail

+0

@ в другом месте: не стоит беспокоить капитана :) Надеюсь, вы понимаете ситуацию;) – user1336087