3

我定义了一个结构数据类型:

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。谢谢!

4

5 回答 5

2

当你使用 时scanf,你需要一个分配的内存块来写入。当您为它分配内存时namemalloc即使您只是分配一个字节(如@billz 指出的那样),因为您现在有一个有效的内存地址。但是你必须分配足够的内存,否则你迟早会覆盖一些东西并造成麻烦。

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

当您将字符串文字分配给指针name( pnode->name = "Jim";) 时,您只是将其设置为内存中硬编码字符串的地址。如果你试图修改它,就会发生不好的事情,所以除非你使用 const 指针,否则永远不要这样做。

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

于 2012-12-17T03:02:08.783 回答
2

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

于 2012-12-17T03:07:06.967 回答
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.

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

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

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

于 2012-12-17T03:08:46.593 回答
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;
}
于 2012-12-17T06:11:30.873 回答
0

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

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

你也可以通过做一个静态缓冲区

typedef struct LinkNode LinkNode;
struct LinkNode {
    char name[256];
    LinkNode *next;
};

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

于 2012-12-17T03:09:52.773 回答