placement of unary operator when using pointers in C - c

I am trying to learn about pointers in C, and don't understand why the unary * operator was appended to the end of the word "node" in the following code snippet:
struct node* CopyList(struct node* head) {
/* code here */
}
From my understanding of pointers, one can create a pointer with a statement like
int *pointerName;
and assign a "pointee" to it with a statement like
pointerName = malloc(sizeof(int));
and then dereference the pointer with a statement like
*pointerName = 4;
which will store the integer value 4 in the 4 bytes of memory (pointee location) which is "pointed to" by the pointerName pointer.
WITH THAT BEING SAID, what does it mean when the * is appended to the end of a word, as it is with
struct node*
???
Thanks in advance!
http://cslibrary.stanford.edu/103/

The location of the * ignores the whitespace between the base type and the variable name. That is:
int* foo; // foo is pointer-to-int
int *bar; // bar is also pointer-to-int
In both cases, the type of the variable is "pointer-to-int"; "pointer-to-int" is a valid type.
Armed with that information, you can see that struct node* is a type, that type being "pointer-to-node-structure". Finally, therefore, the whole line
struct node* CopyList(struct node* head)
means "CopyList is a function taking a pointer-to-struct node (called head) and returning a pointer-to-struct node"

int *pointerName; is the same as int * pointerName; or int* pointerName;. The data type is int* in all those cases. So struct node* is just a pointer to struct node.

struct node* CopyList
To understand better you should read it from right to left. Which says CopyList is a function returning a pointer to node.

You can use '*' either with type or with function name/variable name.But it is suggested to use it with return type while declaring methods, like shown below
struct node* CopyList(struct node* head) {
/* code here */
}
when declaring pointers of a type use * with the variable name. like shown below,
int *ptr;
Declaring in that way increases readability.
For example consider this case,
int* a,b,c;
The above statement is appearing like declaring three pointer variables of base type integer, actually we know that it's equals to
int *a;
int b,c;
Keeping the * operator near the data type is causing the confusion here, So following the other way increases readability, but it is not wrong to use * in either way.

node* means that the following function/variable/structure has type 'pointer to type node'.

Related

How to typecast void to struct/union to access fields?

I am getting the error, "Member reference base type 'void' is not a structure or union", when trying to print out a field of a structure I created.
This is the for loop that increments through a singly-linked lists nodes so long as the node is not null:
for (NODE *temp = sList->head; temp!=NULL;temp=temp->next){
printf("DocNo: %d \n",*(int)temp->dataPtr->docNum);
}
My NODE structure looks as follows (contains the dataPtr field):
typedef struct node{ //node structure definition (the individual nodes in the list)
void* dataPtr;
struct node* next;
} NODE;
My PRINTJOB struct (contains the docNum field):
typedef struct printJob{
int docNum;
int requestPri;
int pageNums;
int numCycles;
} PRINTJOB;
Additionally, I created a pointer to the PRINTJOB structure and populated the fields with values, and then called an insertList() function that takes a pointer to a created list, and the pointer to a populated PRINTJOB structure.
How do I access the fields of PRINTJOB?
Okay, temp is a pointer to a NODE. So temp->dataPtr is a pointer to void *. If now that data is in fact a pointer to a PRINTJOB, you need to tell the compiler about it, so you could do the following:
PRINTJOB * pj = (PRINTJOB *)temp->dataPtr;
int docNum = pj->docNum;
To do both in a single line, do it like you'd do it in algebra; replace pj with its definition from the first line, so pj->docNum becomes:
(PRINTJOB *)temp->dataPtr->docNum
But the problem here is that dereferencing a pointer has a higher precedence than casting, so what the compiler sees is actually the following:
(PRINTJOB *)(temp->dataPtr->docNum)
First dereference everything, then cast it. Yet that way you'd try to access docNum of the void pointer dataPtr, which will not work. So you need to use parenthesis to change the order of operations:
((PRINTJOB *)temp->dataPtr)->docNum
Now the compiler first does one derference, then the cast, and finally another derefence. There is no need to cast to int, the compiler knows that docNum of a PRINTJOB is of type int.

How does struct Node *ptr = malloc(sizeof(*ptr)) work?

I'm a C beginner, and I came across this code while trying to implement a linked list.
struct Node *ptr = malloc(sizeof(*ptr));
The Node struct looks like this:
struct Node {
int data;
struct Node *next;
};
I'm trying to understand the first line. It seems as if malloc(sizeof(*ptr)) already knows the contents of ptr. What exactly is happening on the left side and is it happening before malloc is called?
It seems as if malloc(sizeof(*ptr)) already knows the contents of ptr.
Actually, it doesn't. The sizeof operator doesn't actually evaluate its operand (unless it's a variable length array), it just looks at its type. This means that ptr isn't actually dereferenced and is therefore a safe operation.
Only use paranthesis with sizeof if there's a type you'd like to know the size of. If you have an expression, like *ptr, it's enough to write:
struct Node *ptr = malloc(sizeof *ptr); // <- no parenthesis
The expression *ptr dereferences the pointer so it becomes a struct Node and that's what the sizeof is returning the size for.
sizeofexpression - Returns the size, in bytes, of the object representation of the type of expression. No implicit conversions are applied to expression.
It's the same size you get if you do:
struct Node *ptr = malloc(sizeof(struct Node)); // <- parenthesis needed
but the first alternative is often preferable for clarity.
You need to allocate a memory for an object of the type struct Node declared like
struct Node {
int data;
struct Node *next;
};
So in the call of malloc you need to specify the size of the memory to be allocated for an object of this type. The function malloc returns a pointer to the allocated memory.
So you can write
struct Node *ptr = malloc( sizeof( struct Node ) );
On the other hand, the expression *ptr has the type struct Node. That is the declared pointer ptr has the pointer type struct Node * and dereferencing such a pointer like *ptr yields an expression of the type struct Node.
So you may rewrite the above record also like
struct Node *ptr = malloc(sizeof(*ptr));
because in this case sizeof( struct Node ) is equivalent to sizeof( *ptr ).
That is the compiler needs to know the type of the operand of the operator sizeof that to determine the size of an object of that type.

Manipulating linkedlists in C

Why do we have to pass a pointer to a pointer to manipulate a linked list? Why can't we just pass the pointer? I just dont understand the internals of what is happening logically.
I see it as passing in the pointer to the list would suffice, but apparently not.
It depends on your linked list implementation, but for the sake of argument, if you have implemented, say, a push function, like this:
typedef struct linked_list linked_list;
struct linked_list
{
int value;
linked_list *next;
};
void push(linked_list **head, int value)
{
linked_list *temp = *head;
*head = malloc(sizeof(linked_list));
(*head)->value = value;
(*head)->next = temp;
}
then the pointer to a pointer is necessary because, otherwise, you would be modifying push's local head variable, and not the caller's.
In C if you want to pass a parameter which is possibly modified by the function you pass a pointer to the variable containing the modified value:
void swap(int *i, int *j) // modifies the two parameter.
Now if this parameter is itself a pointer, you have to pass a pointer to a pointer. Take for example the function insert which insert a cell in front of a list. If you represent the list as a pointer to its first element, then this pointer has to be modified. So you pass a pointer to it:
with
typedef struct cell *list
void insert(list *pl, struct cell *pc)
^^
Since list is a pointer itself it is a pointer to a pointer since list * is the same as struct cell **.
There's no one line answer to this
Have at look at page no.12 (push()) in this document: http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
Best explanation according to me.

Trouble dereferencing double pointer

I'd like to implement a stack using a linked list.
In order to implement pop() for my stack, I have the caller pass a double pointer (pointer to a pointer) that (eventually) points to the top of my stack ( first entry in linked list ).
The reason why I'm doing it this way is because this way the caller can keep a static pointer to the stack.
My linked list element struct :
struct Element {
int value;
struct Element *next;
};
pop() implementation:
int pop (struct Element **stack) {
int popped_value = *stack->value;
*stack = *stack->next;
return popped_value;
}
The issue I have is trying to dereference the double pointer **stack. This code generates the following error:
error: request for member ‘value’ in something not a structure
error: request for member ‘next’ in something not a structure
In my mind, either *stack->value or **stack.value should work to retrieve popped_value, but I get the identical error.
-> has higher precedence than the dereference operator, so that's like trying to dereference stack->value since the -> gets done first, and * done second. You need to use parentheses:
int popped_value = (*stack)->value;
*stack = (*stack)->next;
Or, as wallyk suggested in the comments, dereference the argument to get a single pointer and use that:
struct Element *sip = *stack;
int popped_value = sip->value;
*stack = sip->next;
-> has higher operator precedence than dereferencing (*) in this line:
*stack->next
You are saying:
*(stack->next)
Which fails since stack->next doesn't make sense.
You want:
(*stack)->next
instead.

Is there a difference between int* and Type*?

I am implementing a queue in C. I have a struct like:
struct Node {
Node* next;
Node* previous;
// data
}
Because next and previous are just pointers, does it make a difference if I use Node* or int*? eg:
struct Node {
int* next;
int* previous;
// data
}
Not only does it bring clarity to your code (which is important, the larger your project gets), pointer math only works properly if you're doing the math on the correct type. In your instance, adding 1 to a Node* would result in adding sizeof(Node) to the base pointer, which is almost guaranteed not to be == sizeof(int).
For the example you gave, it wouldn't likely matter (but you'll need a cast).. but do yourself a favor and get in the good habit now of using the correct types.
Using int * is incorrect and results in undefined behavior. You can use either Node * or void *, but if you use any type other than Node *, it's going to require a cast (or implicit conversion, e.g. via an assignment) back to Node * before you can dereference it.
Yes it does. Node is not an int (Node will be larger that int), so a pointer to int or a pointer to Node will make a difference.
Everybody is right about everything.
The key point is that even though you may know that the internal representation of a pointer is an address, regardless of data type, C makes no such assumption.
Including an explicit type allows the compiler to do a better job checking your code.
Of course, you can always cast the pointer to a different type but then you need to used the casted-type in its proper context.
By the way, the strict C I learned (back in the Jurassic age) would not allow your first example (C++ does and so do some modern C compilers). Instead you would have to say
struct Node {
struct Node* next;
struct Node* previous;
// data };
When you use int *, You mean that you are pointing to an integer, and when you use Node *, it means you are pointing to a node.
The difference is in size of pointed space by pointer. When its int *, pointer++ will shift pointer by sizeof(int) and when its Node *, pointer++ will shift the pointer by sizeof(Node).
If there is
Node * pNode;
the expectation is to be able to write expressions like following without any cast
(*pNode).next = ...
pNode->next = ...

Resources