3

I define a struct data type:

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

And call it in main(): Example1:

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

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

It doesn't work, unless add one line: Example 2

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

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

But the following code works: Example 3

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

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

So what's the problem? I have been assigned memory to pnode, why scanf() doesn't work? I'm using VS2010. Thanks!

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
fishiwhj
  • 819
  • 2
  • 11
  • 22

5 Answers5

2

When you use scanf, you need an allocated block of memory to write to. When you allocate memory for name with malloc it works, even if you are just allocating one byte (like @billz pointed out), because you have a valid memory address now. You have to allocate enough memory though, or you will overwrite something and cause trouble sooner or later.

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

When you assign a string literal to the pointer name (pnode->name = "Jim";), you are merely setting it to the address of a hardcoded string in memory. If you try to modify it bad things will happen, so never do this unless you are using a const pointer.

Bottom line, name is just a pointer, to do anything with it, you need it to point to something valid.

imreal
  • 10,178
  • 2
  • 32
  • 48
2

When you allocate memory for the structure, it only creates memory for the entire node but not the pointer (name) that is used within. So you have to allocate memory for it explicitly. 1. you did a malloc for pnode->name, allocating memory and then try writing to it 2. pnode->name = "some string", by doing this you are allocating memory and storing the value in it. Hence these snippets work.

Ash
  • 693
  • 1
  • 6
  • 9
1

scanf() has been around for decades. What do you think is the problem? Your code or scanf? :).

In the first example, LinkNode *pnode = (LinkNode *) malloc(sizeof(LinkNode)); allocates a LinkNode object, but does not initialize the char *name. Hence since its a memory location, it contains a junk address until it has been assigned.

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

And this is exactly what you do. In your 2nd Example, you create space for your string data, and then assign it to pnode->name.

In your 3rd example, you assign pnode->name to a constant string.

This is how C pointers work.

Now coming to scanf(): it will read input until a whitespace is encountered, and assign it, formatted, to a character array buffer. Hence you will need a stack-initialized character array, or dynamically created character array(using malloc)

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
1

As you can use C++, I'd like to suggest C++ way. See my sample code and comment

#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;
}
billz
  • 44,644
  • 9
  • 83
  • 100
0

LinkNode consists of two pointers. In a 32-bit architecture, sizeof(LinkNode) equals 8 bytes (4 bytes for each pointer).

When you get memory for your struct, you will get enough space for two pointers, but any data it points to will have to have its separate memory allocated. Therefore the correct way to do what you want is to do two mallocs. One for the struct, and one for the internal string buffer.

You can also have a static buffer by doing

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

In which case, allocating memory for LinkNode, will get enough memory for the internal buffer as well.

Panda Pajama
  • 1,283
  • 2
  • 13
  • 31