【问题标题】:Why have they used function strdup in K&R section 6.5?为什么他们在 K&R 第 6.5 节中使用了函数 strdup?
【发布时间】:2014-11-01 09:03:52
【问题描述】:

The C Programming Language by KNR - 第 2 版,第 6.5 节中,他们定义了一个函数 strdup,因此:

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);

【问题讨论】:

  • 您需要先完成 strdup 函数在某处执行的 malloc(),然后才能将 strcpy 用于字符指针变量。 word 必须指向有效的内存。当第一次实例化它时,它可能指向任何地方。
  • 你认为这是在哪里复制? “将字符串复制到结构的成员上”——不,这不是它正在做的事情......那个成员是一个指针,而不是一个数组。
  • @Scooter 本质上,我想知道通过 malloc() 显式分配背后的原因。我的印象是指针参数的声明也会为相关数据类型分配内存。
  • @Jim Balter - 嗯...这只是一种说法,请记住最终结果...成员最终指向的字符串。
  • @captainsomewhere 不,指针的声明不会为其指向的内存进行任何隐式分配。程序员必须明确地做到这一点。

标签: c kernighan-and-ritchie


【解决方案1】:

如果使用“类似”

strcpy(p->word, w);

那么程序将有未定义的行为,因为 1) p->word 没有被初始化并且有任何未指定的值;并且 2) 此语句正在尝试写入未分配的内存。

如果你将分配内存并用内存的有效地址初始化 p->word 然后使用“类似的东西”

strcpy(p->word, w);

那么实际上你会自己编写strdup的相同实现。

【讨论】:

  • 那么,如果 addtree 接收结构本身而不是指向结构的指针,“类似的东西”会起作用吗?
  • @captainsomewhere 例如,如果结构有一个足够大的字符数组,可以将字符串作为参数传递,那么您可以简单地将参数复制到数组中。
  • @captainsomewhere:它与char * 是否在结构内独立。它与结构本身无关。
  • @captainsomewhere 不,那是行不通的,因为结构本身 still 不提供单词指向的记忆。并且传递结构本身然后存储到其中只会存储到临时堆栈位置,并且当函数返回时更改将丢失。你被反复告知,一个指针,比如word,在你设置它指向某个东西之前不会指向任何东西……你需要开始听。
【解决方案2】:

首先你需要为p->word分配内存,然后你可以使用strcpy(p->word, w);,因为word是一个char指针,之前没有分配内存。

所以如果不分配内存就调用strcpy(p->word, w);,会导致Undefined behavior.

【讨论】:

  • 罗杰。不能投票,没有足够的声誉。感谢您的链接。
  • @captainsomewhere:船长别担心 :) 希望你了解情况;)
猜你喜欢
  • 2021-01-23
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-21
  • 2012-03-14
相关资源
最近更新 更多