This is my first post. I'm very confused with the C's pointer and its relation to struct. I've searched for more information but can't really conclude them. For example given this struct definition
typedef struct node
{
int info;
struct node *next;
}NODE;
Then what's the differences and effects of these four declarations;
1. NODE *node1 = malloc (sizeof(NODE));
2. NODE *node1 = (struct node *) malloc (sizeof(NODE));
3. NODE *node1 = (struct node *) malloc (sizeof(NODE *));
4. NODE *node1 = malloc (sizeof(NODE *));
Thanks in advance.
These are equivalent and allocate a block of memory the same size as a NODE struct.
1. NODE *node1 = malloc (sizeof(NODE));
2. NODE *node1 = (struct node *) malloc (sizeof(NODE));
These are just wrong
3. NODE *node1 = (struct node *) malloc (sizeof(NODE *));
4. NODE *node1 = malloc (sizeof(NODE *));
Line 3 allocates a memory block the size of a pointer to a NODE structure. The cast allows you to assign it without any errors being thrown, and possibly without warnings. But it's not what you want.
Line 4 does the same as line 3. malloc returns a void * which doesn't require casting, but a good static analyzer should give you a warning.
Either way, lines 3 & 4 are recipes for buffer overflows and undefined behavior.
Lines 3 and four would be correct if written thus:
NODE **ptr = malloc(sizeof(NODE *));
// node1 is a pointer to (heap) memory block of size NODE
1. NODE *node1 = malloc (sizeof(NODE));
// same as 1. (but 1. is the preferred way)
2. NODE *node1 = (struct node *) malloc (sizeof(NODE));
// (Wrong) node1 is a pointer to (heap) memory block of size pointer to NODE (a pointer to _usually_ 4 bytes)
// but you cast it to pointer to NODE (a pointer to more than 4 bytes)
3. NODE *node1 = (struct node *) malloc (sizeof(NODE *));
// (Wrong) same as 3
4. NODE *node1 = malloc (sizeof(NODE *));
Stick with number 1. as it's the common way to allocate an object in the heap (dynamic allocation): Object *object = malloc(sizeof(Object)). You can forget about 2. 3. 4. which complicate the issue and really not what you need.
Given:
NODE *node1 = malloc (sizeof(NODE));
NODE *node1 = (struct node *) malloc (sizeof(NODE));
NODE *node1 = (struct node *) malloc (sizeof(NODE *));
NODE *node1 = malloc (sizeof(NODE *));
ALL ARE BAD
3 and 4 are really bad
3) and 4) are not allocating enough memory for the struct, but only enough memory to hold the pointer to a struct (say 4 bytes on a 32-bit system) and then telling the compiler to treat that memory as if it was enough to occupy a NODE
1) is correct way to allocate enough memory for the structure (caveat other issues described below)
2) is bad practice because what you really mean is:
NODE *node1 = (NODE *) malloc(sizeof(NODE));
even though NODE is typedef struct node (2) says that you know that for sure.
Having said that,
All of them are bad practices for a reason explained later on below.
What you really want to do in practice is something like this:
Only use typedefs when you want to keep things really opaque about the inner structure (the way stdio does FILE) it's better practice to use struct foo bar; in your declaration than typedefing the struct. Especially when the structure is exposed to other parts of the program.
typedef is better used when you want to ensure that a type is uniformly interpreted on different architectures, e.g. the use of typedef unsigned long long uint64_t vs typedef unsigned uint64_t on 32-bit and 64-bit intel x86 cpus in stdint.h
A good example
struct node {
struct node *next;
size_t n_dlen;
void * n_data;
};
int main() {
struct node *node;
node = malloc(sizeof(*node));
}
Notice that I used sizeof(*node) instead of sizeof(struct node), because if I decide later on that node should be some other type say struct new_node * then all i have to do is change the declaration and the sizeof(*node) will still be okay.
Related
What I did :
I added a pointer in the parameter of malloc(struct Node *) which is usually malloc(struct Node).
Problem :
When I am allocating memory for the size of a pointer then how the code is working?
malloc() is allocating 8 bytes of memory and returning the pointer
So the pointer points to an 8 bytes memory block which but further I am storing more data in it.
struct Node
{
int data;
struct Node *next;
};
struct Node *GetNode(int data)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node *));
node->data = data;
node->next = NULL;
return node;
}
Difference in size:
I know that malloc is allocating different sizes because I did this
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void main(){
int i = sizeof(struct Node);
int j = sizeof(struct Node *);
printf("%d,%d", i, j);
}
Output
16,8
What you've done is undefined behavior. It could work (on some systems, on certain days of the week), or it could crash, or it could produce incorrect results in seemingly unrelated calculations.
Imagine you rent a garage space for your truck, but to save money you request a space for a car. What happens when you drive your truck in? Maybe it fits, maybe you wreck the truck, maybe you destroy the garage.
So don't do that, and to help you find cases where you've made similar mistakes, build with Address Sanitizer. It will log when you access memory in an invalid way.
UB is a fickle mistress. Sometimes agreeable; sometimes not.
That is why you should use a syntax that makes it less likely to make mistakes:
struct Node *node = (struct Node *)malloc(sizeof(struct Node *)); // bad
struct Node *node = malloc( sizeof *node ); // good
No casting, and no redundancy.
I would even recommend using typedef's to free yourself from "struct, struct, struct".
typedef struct s_node
{
int data; // use more indentation, please. whitespace is cheap.
struct s_node *next;
} Node_t;
/* ... */
Node_t *node = malloc( sizeof *node ); // better
Finally, a lot of hours are wasted tracking down bugs that appear and disappear. Until performance becomes a real issue that you understand, I'd recommend using calloc() as the go-to allocation function:
Node_t *node = calloc( 1, sizeof *node ); // best
You can sleep easier knowing the byte values will be repeatable from run to run.
I've created a Stack structure in C. When the stack is initialized with a value, I am able to print it back and receive the correct output. However, after pushing a new string, the print function prints what appears to be a random character (ASCII 177).
Originally, I implemented this project with pointers, but I was unable to get it working. Instead, I opted to only use a pointer for the Node *nodes member of Stack. That way, when I need to grow the stack, I can just multiply the amount of memory required by Stack.size. However, this approach has not worked yet either.
#define MAX_DATA 64
struct Node{
char val[MAX_DATA];
};
struct Stack{
int size;
struct Node *nodes;
};
These are used as follows:
struct Node node = {.val = "Test"};
struct Stack stack = newStack(node);
printStack(stack);
The newStack function initializes nodes properly. For the sake of inclusion:
struct Stack newStack(struct Node node)
{
struct Stack stack;
stack.size = 1;
stack.nodes = (struct Node*) malloc(sizeof(struct Node));
stack.nodes[0] = node;
return stack;
}
The stack is then printed iteratively in printStack(), with stack.size being the upper bound of the for-loop.
The trouble comes when I try to run:
struct Node node2 = {.val = "Test1"};
push(stack, node2);
printStack(stack);
The push function aims to create a temporary stack and assign the value of the stack to it. After this, the size is incremented, the pointer to the nodes is freed, and new memory is allocated, with room for a new member at the end.
void push(struct Stack stack, struct Node node)
{
struct Stack temp_stack = stack;
stack.size += 1;
free(stack.nodes);
stack.nodes = (struct Node*) malloc(sizeof(struct Node) * stack.size);
for(int i = 0; i < temp_stack.size; i++){
stack.nodes[i] = temp_stack.nodes[i];
}
stack.nodes[stack.size - 1] = node;
}
Needless to say, this doesn't execute properly.
The expected output would be:
Test
Test1
But, instead, I receive only ASCII-177. It is also worth noting that the execution hangs after it prints that and moves to the new line. This results in Aborted (core dumped).
Am I improperly freeing and re-allocating memory? Any help would be appreciated. Thank you in advance!
It's worth remembering that in C, passing a struct to a function is pass-by-value, i.e., the function gets a copy of the struct. All members of the struct, including pointer variables (but not whatever the pointer references), are duplicated.
So in the push function, think about what happens to the original when you modify this copy (e.g., stack.size += 1, and also when you free() the stack.nodes.
Thank you to peekay for the recommendations. I ended up doing a re-write. It became quite a bit simpler. I did remove a layer of "visibility" by storing the nodes as a pointer, but I suppose this implementation is a bit more true to the data structure.
Node is implemented as a means to hold data, and the user doesn't interact with it directly. It also points to the following Node. Stack is implemented to hold the top Node, and also the size of the Stack.
Node:
struct Node{
char val[MAX_DATA];
struct Node *next;
};
Stack:
struct Stack{
struct Node *top;
int size;
};
Push:
void push(struct Stack *stack, char *newVal)
{
struct Node *newNode;
newNode = (struct Node*) malloc(sizeof(struct Node));
strcpy(newNode->val, newVal);
newNode->next = stack->top;
stack->top = newNode;
stack->size++;
}
Usage:
struct Stack stack;
newStack(&stack);
push(&stack, "Test");
push(&stack, "Test1");
push(&stack, "Test2");
push(&stack, "Test3");
Complete Code
Updated, accessible Nodes
Here is the code to create a link in the list which i read off the internet to try understand linked lists in c:
//insert link at first location
void insertFirst(int key, int data) {
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
I am really not understanding how the following line works as a whole:
struct node *link = (struct node*) malloc(sizeof(struct node));
and more specifically:
(struct node*)
because my understanding is that the asterisk must come before the pointer name and yet its at the end of the struct name. Please correct me if I'm wrong and please if you can, explain how this works?
Casting the return value of malloc is unnecessary.
As per standard 7.22.3.4
The malloc function returns either a null pointer or a pointer to the
allocated space.
You should check its return value to know whether it succeeded or not.
What malloc does?
The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
my understanding is that the asterisk must come before the pointer name and yet its at the end of the struct name
Here you are not dereferencing anything. Rather you are typecasting. (which is again I would repeat that unnecessary).
struct node* here is a type of the pointer variable. Same way int or double is a type, this is also a type.
Assume you have to create database of a students having some entities.
struct node
{
int id;
char name [100];
};
Next thing,
struct node *link = (struct node*) malloc(sizeof(struct node));
How above line works ? you need to create one node or memory, So how will you create it, use malloc(). Next things how much memory you are going to create , equal to total size of your data members of structure, so for that its using
struct node *link = malloc(sizeof(struct node));
here link is nothing but name of dynamic memory we created to put some data into that. once memory is created put some data into memory.
scanf("%d %s\n",&link->id,link->name);
similarly you can do above task no of times.
typecasting is not compulsory or not advised to do. So below statement is correct.
struct node *link = malloc(sizeof(struct node));
In order to create a linked list you have to allocate the units -in your case :
struct node
so either you pre-allocate the memory for the list or dynamically allocate them every time you add a node to the list, the memoery for the node has to be recruited from somewhere, in this case - malloc does that.
Hope that helps
struct node *tempNode = (struct node*) malloc(sizeof(struct node));
//and
struct node *tempNode = malloc(sizeof(struct node));
struct node *tempNode = (struct node*) malloc(sizeof(struct node));
you're dynamically allocating space to a node pointer tempNode and typecasting it to be a struct node* type. (pointer to structure)
struct node *tempNode = malloc(sizeof(struct node));
The same as above, except without the explicit typecast (struct node*)
There is no difference. Since malloc returns type void *, it can be assigned to a variable of any pointer type without casting. As John Bode mentioned, casting the result of malloc is considered bad practice because it may mask the compiler error that would result from having some other definition of malloc.
Since you are casting it correctly there's no difference between the two.
But the cast is generally frowned upon in C since a void* can be implicitly converted into any other (data) pointer type.
Also see this C FAQ entry: What's wrong with casting malloc's return value?
A third one is there:
struct node *tempNode = malloc(sizeof *tempNode);
which is better since it makes for less changes in case the type is changed.
With the call to malloc, memory is allocated that has the size of the struct node in bytes. It returns a void* to the allocated memory.
Now the thing is: both of your lines do exactly the same, but the second line will lead to a warning when compiled with a C++ compiler.
C allows implicit conversion of a void* to a different pointer type, whereas the C++ compiler will - at least - warn you, or give you an error.
In the books I read that the syntax for malloc is malloc(sizeof(int)) but in one of doubly linked list program I see the following:
newnode=(struct node *)malloc(sizeof(struct node))
What is (struct node*) doing here? What is this entire code doing? btw, the code for the struct in the program is as below.
struct node
{
char line[80];
struct node *next,*prev;
};
struct node *start=NULL,*temp,*temp1,*temp2,*newnode;
Thank you
The code is dynamically creating a pointer to a single type of struct node. In most versions of C, the (struct node *) cast is not needed, and some argue that it shouldn't be used. If you remove the cast, it will be a void*, which can be used for any type.
Therefore:
newnode = (struct node*)malloc(sizeof(struct node));
is roughly equivalent to:
newnode = malloc(sizeof(struct node));
See: Specifically, what's dangerous about casting the result of malloc?
Note 1: If you are using Visual Studio to write your C code, it will give you red underlining if you don't cast the result of malloc. However, the code will still compile.
Note 2: Using malloc in C++ code requires you to cast the result as shown in your example.
You ran into a very bad code. C programmers never cast a result of malloc(). Not only it is not needed but can be harmful.
You should pass the number of bytes that you want malloc to allocate as argument. That is why in this code sample you use sizeof(struct node) telling C to allocate the number of bytes needed for a struct node variable. Casting the result like is shown in this code is bad idea by the way.
malloc returns a void pointer .
(struct node*) does a explicit conversion from void pointer to the target pointer type
"malloc" returns a void-pointer. (struct node *) is type-casting the result of malloc to a "node struct pointer", which is (undoubtibly) what "newnode" is.