pointers in C and use in linked list - c

I am struggling with understanding structs and pointers, and thus, struggling to understand examples of linked lists in both my textbook and online.
What does the following code mean:
(struct NODE *)malloc(sizeof(struct NODE));
Will someone please provide a detailed explanation?
I understand that something is being allocated memory (the size in bytes of struct NODE), however, I don't understand what
(struct NODE *)
means.

Function malloc() returns address of allocated memory. Return type of malloc() function is void* (it don't know for which type of data you are allocating memory), to assign it to pointer of your structure type you typecasts it into required type. So in you expression (struct NODE *) is typecast instruction:
(struct NODE *) malloc (sizeof(struct NODE));
^
| ^
Typecast | call of malloc function with argument = sizeof(struct NODE)
Generally, you should avoid typecast a returned value from malloc/calloc functions in C ( read this: Do I cast the result of malloc? )
In C syntax of typecast is:
(rhsdatatype) data;
rhsdatatype should be in parenthesis before data.
Sometime in programming you need typecast: for example.
int a = 2;
int b = 3;
double c = a / b;
This code outputs 0.0 because 2/3 both are integers to / result will be int that is 0, and you assigns to double variable c = 0. (what you may not wants).
So here typecast is solution, new code is:
int a = 2;
int b = 3;
double c = (double)a / (double)b;
it outputs real number output that is: 0.666.

malloc returns void*. (struct NODE *) is a cast of this to a pointer to NODE.
This cast is not required in C. Use of it is often considered poor style since it can cause bugs if you forget to include <stdlib.h> for a declaration of malloc.

Related

Error with malloc while creating memory for list of struct pointers

For some reason, while trying to create an array of pointers of a struct called Node, I keep getting an error:
Node ret[2] = (struct Node*)malloc(2*sizeof(Node));
error: invalid initializer
Can someone please help me with that?
Node ret[2] = (struct Node*)malloc(2*sizeof(Node));
should probably be:
Node *ret = malloc(2 * sizeof(*ret));
That's because you need a pointer to the memory, not an array. With an array, it's initialisation, which would require a braced init list. Note that this only provides memory for the pointers, not the things they point at - they need to be allocated separately if you wish to use them.
You'll probably notice two other changes as well:
I've removed the cast on the malloc return value. This serves no purpose in C since the void* returned can be implicitly cast to other pointer types. In fact, there are situations where explicit casts can lead to subtle problems.
I've used *ret as the variable to get the size rather than the type. This is just habit of mine so that, if I change the type to (for example) tNode, I only have to change it in one place on that line - yes, I'm basically lazy :-) Note that this is just a preference, doing it the original way has no adverse effect on the program itself, just developer maintenance.
I think your struct is typedef ed
Node ret[2] = ( struct Node* ) malloc( 2 * sizeof(Node) );
it should be
Node *rec[2] = { malloc(sizeof(Node)) , malloc(sizeof(Node)) };
or
Node *rec = malloc(2*sizeof(Node));

How to allocate memory to struct pointer using malloc.h header?

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct student
{
char name[25];
int age;
};
int main()
{
struct student *c;
*c =(struct student)malloc(sizeof(struct student));
return 0;
}
What is the wrong with this code? I tried times by alternating this code to allocate memory to struct pointer. But this error comes when compiling:
testp.c:15:43: error: conversion to non-scalar type requested
*c =(struct student)malloc(sizeof(struct student));
^
I'm using mingw32 gcc compiler.
What is the wrong with this code?
Ans: First of all you change that "is" to "are", there are two major problems, atleast. Let me elaborate.
Point 1. You allocate memory to the pointer, not to the value of pointer. FWIW, using *c (i.e., de-referencing the pointer without memory allocation) is invalid and will result in undefined behaviour.
Point 2. Please do not cast the return value of malloc() and family in C. The cast you used is absolutely wrong and proves the authenticity of the first sentence.
To solve the issues, change
*c =(struct student)malloc(sizeof(struct student));
to
c = malloc(sizeof(struct student));
or, for better,
c = malloc(sizeof*c); //yes, this is not a multiplication
//and sizeof is not a function, it's an operator
Also, please note, to make use of malloc() and family , you don't need the malloc.h header file. These functions are prototyped in stdlib.h.
EDIT:
Suggestions:
Check for success of malloc() before using the returned pointer.
Always free() the memory once the usage is over.
The recommended signature of main() is int main(void).
This worked (on C and C++).
Since you originally included both tags.
change
*c =(struct student)malloc(sizeof(struct student));
to
c =(struct student*) malloc(sizeof(struct student));

Malloc syntax in C

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.

Struct memory allocation fault

I am writing a C project with pointers and structs, and right now facing this problem:
There is a structure
struct Customer
{
char Name[80];
char Address[40];
int ID;
int Pnumber;
};
and I am gonna make a dynamic array of this structs with *line_count* number of members. I use this code, but it crashes a program:
struct Customer* ph;
ph = (struct Customer*)malloc(line_count * sizeof(struct Customer));
What am I doing wrong?
Good:
struct Customer* ph;
ph = (struct Customer*)malloc(line_count * sizeof(struct Customer));
Better:
struct Customer* ph =
(struct Customer*)malloc(line_count * sizeof(struct Customer));
if (!ph) {
<<error handling>>
...
But frankly, it sounds like the problem is elsewhere in your code.
There's nothing fundamentally wrong with your malloc().
Maybe "line_count" is bogus, maybe "malloc()" is failing (in which case, it should return "NULL") ... or maybe you're accessing the struct incorrectly and/or failing to initialize it correctly.
A stack traceback of the actual crash would be very useful.
The piece of code you are showing might crash only if ph == NULL after the malloc call and you dereference it.
From the malloc man page:
The malloc() and calloc() functions return a pointer to the allocated
memory that is suitably aligned for any kind of variable. On error,
these functions return NULL. NULL may also be returned by a
successful call to malloc() with a size of zero, or by a successful
call to calloc() with nmemb or size equal to zero.

Segmentation Fault in a struct with a pointer to another struct

I'm having some issues with my linked list. I have struct dListNode used as the nodes for the list with a pointer to struct data, which is used as the data storage.
struct data{
int payload;
};
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data *val;
}*dHead, *dTail;
My program compiles fine, but I get a segmentation fault at the line indicated below. What is going on?
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
printf("newnode created\n"); // this prints
newDNode->val->payload = rand() % 1000; //error here?
printf("newnode payload: %i\n", newDNode->val->payload); //seg fault before this is printed
Also, I have already ran this line in the program: srand((unsigned)time(NULL))
NewDNode doesn't have an associated memory allocation to it. So when you do
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
This just allocates memory to newDnode and not to newDnode->val. Since newDNode->val just contains whatever was leftover in the memory at that location (or maybe even 0 (NULL pointer)), and you try to assign a value to the memory location which is neither on the stack nor on the heap, the program complains because you are trying to access unassigned part of memory.
Here's what you should do:
newDNode = malloc(sizeof(struct dListNode));
newDnode->val = malloc(sizeof(struct data));
printf("newnode created\n");
newDNode->val->payload = rand() % 1000;
printf("newnode payload: %i\n", newDNode->val->payload);
And as a tip, always try to not cast the result returned by malloc (or any other memory allocation function). Its considered bad practice.
You problem is that you never initialized the pointer val:
newDNode->val->payload = rand() % 1000;
newDNode is allocated, but none of the fields are initialized, so dereferencing val will likely cause that segmentation fault.
So you will need to allocate something for val before you access it.
newDNode = malloc(sizeof(struct dListNode)); // Allocate "dListNode"
newDNode->val = malloc(sizeof(struct data)); // Allocate "data"
newDNode->val->payload = rand() % 1000;
You have a slight misunderstanding of how the allocation works. You need to allocate each pointer separately.
EDIT : And alternate approach is just to not use a pointer for val in the first place:
// Declare struct as:
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data val;
}*dHead, *dTail;
// Build object like this:
newDNode = malloc(sizeof(struct dListNode));
newDNode->val.payload = rand() % 1000;
val does not point to a valid data structure. Sure, you malloc enough size, but that doesn't mean that val is now all of a sudden a valid pointer. You should initialize newDNode with just the size of a dListNode and then separately initialize newDNode->val to point to some valid chunk of memory large enough for a data structure.
On a side note, you don't need to cast the return value of malloc. That's a C++ thing; in C a void* can be implicitly converted to any other pointer type.
Second, if you typedef your struct types you don't have to write struct all over the place when using them.
You're never setting newDNode->val to point to anything. So when you try to set newDNode->val->payload, you're dereferencing either a null pointer or some random address (i forget which). Neither case is what you want.
I don't really like the idea of malloc'ing both the structs in the same statement. But if you insist on doing it, you'll need to do something like
newDNode->val = (struct data*)((char*) newDNode + sizeof(struct dListNode));
A better way, though, is to change the struct so that val is a struct rather than just a pointer to one. Then sizeof(struct dListNode) includes the size of struct data, and you can access it like newDListNode->val.payload without having to malloc the data part separately or do any tricky pointer math. (Drawback being, you'd have to copy the structs to store them in an array, swap them around, etc.)

Resources