2

I'm using the following code to push a new node at the front of the linked list. I have some doubts regarding some concepts.

void push(struct node **head, int data)
{
    // create a new node
    struct node *new_node;
    new_node = malloc(sizeof(struct node));

    // add data
    new_node->data = data;

    // add node to front of list
    new_node->next = *head;
    *head = new_node;
}
  1. When I assign the value of new_node to *head in *head = new_node, and then return, does the pointer new_node get destroyed, as it's an automatic variable?

  2. Should the memory pointer by new_node, assigned to it by the malloc call still be legal to access after new_node is destroyed, as it's on the heap, and was never de-allocated?

  3. We're just using the new_node as a placeholder to store an address to some memory, and after we're done with the assignments and stuff, we let it go. Then should it matter that new_node is of type struct node, for all pointers are just integers, and we're just using it to store a memory address. Where does the pointer type become relevant i.e. why do I have to declare the data type of the pointer to match the pointee's datatype?

  4. Can I just declare all pointers as integers and then explicitly typecast them before using, to match the pointee's datatype?

legends2k
  • 31,634
  • 25
  • 118
  • 222
nimbudew
  • 958
  • 11
  • 28
  • 1
    Related: [Why different types of pointer for different data type in c?](http://stackoverflow.com/questions/12530806/why-different-types-of-pointer-for-different-data-type-in-c) – legends2k Jun 17 '14 at 08:53

4 Answers4

2
  1. Yes.
  2. Yes.
  3. No, you're using new_node as a pointer to a structure type, which has a field data and another field next. A void * (or, worse, integer) wouldn't let you do that. The compiler needs the type information to make sense of an expression like new_node->data = data;.
  4. Sure (for some suitable integer type), but why?!
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 4. Was just curious, if we could do that, even theoretically. – nimbudew Jun 17 '14 at 08:32
  • Why would an integer pointer be worse than a void pointer if I try to typecast them as a struct node? Shouldn't the typecasting work evenly for all datatypes? And is typecasting just a way to let the compiler know the datatype, so it can use it appropriately? – nimbudew Jun 17 '14 at 08:40
  • @flipper Because a pointer is at least a pointer, i.e. it tells the reader of your code that "here is the address of something". An integer is generally assumed to not be a pointer. In other words: because code should be *clear* and *understandable*. You seem to not care all that much about those, though. :/ – unwind Jun 17 '14 at 08:45
2

When I assign the value of new_node to *head in *head = new_node, and then return, does the pointer new_node get destroyed, as it's an automatic variable?

What is destroyed is the pointer allocated on the stack, but the malloc'd memory remains (so head is valid), .

Should the memory pointer by new_node, assigned to it by the malloc call still be legal to access after new_node is destroyed, as it's on the heap, and was never de-allocated?

It will be legal, and you can use it.

We're just using the new_node as a placeholder to store an address to some memory, and after we're done with the assignments and stuff, we let it go. Then should it matter that new_node is of type struct node, for all pointers are just integers, and we're just using it to store a memory address. Where does the pointer type become relevant i.e. why do I have to declare the data type of the pointer to match the pointee's datatype?

Pointers are not integers, they may be larger than an integer and they are not signed. First of all you guarantee that the address will fit in the pointer. You can use a void pointer if you don't want to define a struct pointer but then you can not use it easily (without a cast) with the same pointer.

Can I just declare all pointers as integers and then explicitly typecast them before using, to match the pointee's datatype?

No, you can't. Use void pointers for this purpose.

perreal
  • 94,503
  • 21
  • 155
  • 181
  • Actually a pointer can be converted (cast) to any integral type large enough to hold it, and back again. However you shouldn't do this (except for some exceptional cases). – david.pfx Jun 17 '14 at 08:44
2

for all pointers are just integers, and we're just using it to store a memory address.

No! Pointers are just address locations in memory and their size depends on the compiler and the architecture used. There's no guarantee by language that they are integers.

Where does the pointer type become relevant i.e. why do I have to declare the data type of the pointer to match the pointee's datatype?

Type safety. When you've a pointer to a character, it would be of type char*, but casting it into an integer pointer and writing to it may lead to memory corruption. Let me show you an example

char ch = 'a';
char *cp = &ch;
int *ip = (int*) cp;   // type safety lost since the pointer no longer refers to just one character
*ip = 1000;    // memory to which 1000 is written to would span beyond a character's size

When *ip = 1000 is seen by the compiler, it has no way of warning you against this corruption since it believes that the underlying pointee is an integer; an integer can of course hold 1000 and thus compiles it fine; had it been *cp = 1000 this value would be implicitly converted into a value hold-able by a char and thus no memory corruption by it. Also if you'd enabled warnings the compiler will be able to warn you of this narrowing implicit conversion. GCC spits warning: overflow in implicit constant conversion.

Can I just declare all pointers as integers and then explicitly typecast them before using, to match the pointee's datatype?

You certainly can, but don't, for the above reason. Read more about type safety.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • I've been told that the size of an integer is equal to the size of the memory, and hence all memory addresses can be stored as integers. Is that true? – nimbudew Jun 17 '14 at 08:44
  • No, it isn't strictly true. See the comment to your question for a related post. – legends2k Jun 17 '14 at 08:57
1
When I assign the value of new_node to *head in *head = new_node, and then  
return, does the pointer new_node get destroyed, as it's an automatic variable?  

No, it does not. new_node will be valid as long as you free it. Since you do not have any handle to it once the function call is done, its memory is leaked. You cannot get it back.

Should the memory pointer by new_node, assigned to it by the malloc  
call still be legal to access after new_node is destroyed, as it's on the heap,  
and was never de-allocated?  

Same as first answer

We're just using the new_node as a placeholder to store an address to some  
memory, and after we're done with the assignments and stuff, we let it go.  
Then should it matter that new_node is of type struct node, for all pointers  
are just integers, and we're just using it to store a memory address.  
Where does the pointer type become relevant i.e. why do I have to declare the  
data type of the pointer to match the pointee's datatype?  

The pointer should be of the same type as the data it points to. It might need to know the size of the data it is pointing to manage the memory like free etc.

Can I just declare all pointers as integers and then explicitly typecast them  
before using, to match the pointee's datatype?  

You can use void pointers to transfer pointers across functions.

cppcoder
  • 22,227
  • 6
  • 56
  • 81