scanf()在malloc struct成员中不起作用

时间:2012-12-17 02:50:46

标签: c struct malloc scanf

我定义了一个struct数据类型:

typedef struct LinkNode LinkNode;
struct LinkNode {
    char *name;
    LinkNode *next;
};

并在main()中调用它:     Example1:

int main()
{
    LinkNode *pnode = (LinkNode *) malloc(sizeof(LinkNode));

    scanf("%s", pnode->name);
    ...
    free(pnode);
    return 0;
}

它不起作用,除非添加一行:Example 2

int main()
{
    LinkNode *pnode = (LinkNode *) malloc(sizeof(LinkNode));
    pnode->name = (char *) malloc(sizeof(char));

    scanf("%s", pnode->name);
    ...
    free(pnode);
    return 0;
}

但以下代码有效:Example 3

int main()
{
    LinkNode *pnode = (LinkNode *) malloc(sizeof(LinkNode));

    pnode->name = "Jim";
    ...
    free(pnode);
    return 0;
}

那么问题是什么?我已经为pnode分配了内存,为什么scanf()不起作用?我正在使用VS2010。 谢谢!

5 个答案:

答案 0 :(得分:2)

使用scanf时,需要一个已分配的内存块才能写入。当您为name分配malloc的内存时,即使您只是分配一个字节(如@billz指出),因为您现在拥有有效的内存地址。你必须分配足够的内存,否则你将会覆盖一些东西并迟早会引起麻烦。

pnode->name = (char *) malloc(sizeof(char) * <max size of input>);

将字符串文字指定给指针namepnode->name = "Jim";)时,只需将其设置为内存中硬编码字符串的地址即可。如果你试图修改它会发生坏事,所以除非你使用const指针,否则永远不要这样做。

底线,name只是一个指针,对它做任何事情,你需要它指向有效的东西。

答案 1 :(得分:2)

为结构分配内存时,它只为整个节点创建内存,但不为其中使用的指针(名称)创建内存。所以你必须明确地为它分配内存。 1.你为pnode-&gt;名字做了一个malloc,分配了内存,然后尝试写入它 2. pnode-&gt; name =“some string”,通过执行此操作,您将分配内存并将值存储在其中。 因此,这些片段有效。

答案 2 :(得分:1)

scanf()已经存在了几十年。您认为这个问题是什么?你的代码还是scanf? :)

在第一个示例中,LinkNode *pnode = (LinkNode *) malloc(sizeof(LinkNode));分配LinkNode个对象,但不初始化char *name。因此,由于它是一个内存位置,它包含一个垃圾地址,直到它被分配。

There are three correct ways to assign a `char*`:
1. Create dynamic memory space and then assign it to the `char *`
2. Assign it to a constant string such as "Jim" in your example
3. Assign the pointer to another pointer that has been created by either 1 or 2

这正是你所做的。在第二个示例中,为字符串数据创建空间,然后将其分配给pnode->name

在第3个示例中,您将pnode->name分配给常量字符串。

这就是C指针的工作方式。

现在来到scanf():它将读取输入,直到遇到空格,并将其格式化为字符数组缓冲区。因此,您将需要一个堆栈初始化的字符数组,或动态创建的字符数组(使用malloc

答案 3 :(得分:1)

你可以使用C ++,我想建议C ++方式。请参阅我的示例代码和评论

#include <string>
struct LinkNode {
    std::string name;    // let string manage dynamic memory instead of raw pointer
    LinkNode *next;
};     

int main()
{
  LinkNode *pNode = new LinkNode;  // use new instead of malloc
  std::cin >> pNode->name;         // use std::cin instead of scanf    
  delete pNode;
  return 0;
}

答案 4 :(得分:0)

LinkNode由两个指针组成。在32位架构中,sizeof(LinkNode)等于8个字节(每个指针4个字节)。

当您获得结构的内存时,您将获得足够的空间用于两个指针,但它指向的任何数据都必须分配其单独的内存。因此,做你想做的事的正确方法是做两个malloc。一个用于struct,另一个用于内部字符串缓冲区。

您也可以通过

获得静态缓冲区
typedef struct LinkNode LinkNode;
struct LinkNode {
    char name[256];
    LinkNode *next;
};

在这种情况下,为LinkNode分配内存也会为内部缓冲区提供足够的内存。