successive pointer casting in C - c

I am looking through some example code which employs an API to understand how to properly use the API. I came across some code which I found confusing. Below are the relevant chunks of code:
typedef struct myStruct_id{
randomStruct1 var1;
void *var2;
unsigned char *var3;
randomStruct2 var4;
int var5;
}myStruct_name;
//Function Prototype
void randomFunction(const randomStruct1 *in1, const randomStruct2 *in2, void *handle);
//Global Variables
//assuming data1-5 are of the correct types corresponding to randomStruct1, void, etc.
myStruct_name myStruct_var = {data1, data2, data3, data4, data5};
void *handle = (void*)myStruct_var;
void main(){
myStruct_name *local_var = (myStruct_name *)handle;
//Other code here
local_var.var2 = randomFunction(&local_var.var1, &local_var.var4, &(local_var));
}
My understanding is that the variable handle is a null generic pointer, pointing to the variable myStruct_var (which has been type cast as a null generic pointer). In the main function, the variable local_var is a pointer to the struct myStruct_name, pointing to the value of the pointer handle (which is type cast as a pointer to type myStruct_name) which is pointing to the variable myStruct_var. Next the function randomFunction takes as inputs a pointer just to var1, a pointer to just to var2, and a pointer to the variable local_var.
My confusion is this: the function randomFunction requires as input pointers pointing to structs and a null generic pointer. If local_var is already a pointer, why is the address operator (&) required? Is not the value of local_var already an address? Or is my understanding of what is going on with local_var incorrect?
Also, is there a reason why the final input to randomFunction is parenthetical? That is, why is it &(local_var) instead of just &local_var? Are the parenthesis doing something?
Thanks for reading and any responses!
EDIT: Thanks for the responses indicating I am not referring to a null pointer. I'm referring to the void "data type" here as generic.

If your background is in Java or some other "safe" language, pointers can genuinely be very hard to wrap one's head around. But at the core you're just dealing with memory.
First question - Why address of pointer?
Here's some sample code you can play with. It tries to implement a "shallow" swap in two ways.
#include <stdio.h>
typedef struct {int x; int y; int z;} XYZ;
XYZ s1 = {1, 2, 3};
XYZ s2 = {4, 5, 6};
void swap1(XYZ *a, XYZ *b);
void swap2(XYZ **a, XYZ **b);
int main()
{
XYZ *p = &s1;
XYZ *q = &s2;
printf("Before\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
swap1(p, q);
printf("Swap 1\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
swap2(&p, &q);
printf("Swap 2\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
return 0;
}
void swap1(XYZ *a, XYZ *b)
{
XYZ *t;
t = a;
a = b;
b = t;
}
void swap2(XYZ **a, XYZ **b)
{
XYZ *t;
t = *a;
*a = *b;
*b = t;
}
When you compile and run the above code, you'll get something like this:
Before
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 1 2 3 q: 4 5 6
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280
Swap 1
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 1 2 3 q: 4 5 6
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280
Swap 2
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 4 5 6 q: 1 2 3
Addresses: 0x60103c 0x601048 0x601048 0x60103c 0x7ffd29c58288 0x7ffd29c58280
Note that swap 1 didn't do anything, it was only at swap 2, where addresses of the pointers were used, that a swap happened. Also note that s1 and s2 were left unaltered. You might use this function to implement a sort which doesn't need to copy entire structures.
Second question: Why &(local_var) vs. &local_var?
The differences are not functionally significant. It might have been a remnant of a previous expression, cut & paste, anything. Lots of reasons.

Related

Calculate the sum of two numbers and "return" it by using a void function in C with a pointer as parameter

So basically I'd like to sum two numbers and return their value while using a void function in C. I know this is easy peasy by using a normal function returning an int or a numeric type but I wanna work on my pointer knowledge.
I tried creating a pointer inside main() and then passing it as an argument to the void function. Then I calculated my sum in a new int variable and assigned the pointer to point to that specific variable. The problem is I can't "retrieve" it or "find" that area of memory in the main function.
Here's what I've tried:
void testFunction(int a,int b, int *x)
{
int c=a+b;
x=&c;
}
int main()
{
int n1=7;
int n2=90;
int *pointerParam;
testFunction(n1, n2, pointerParam);
printf("Value of pointer is %d\n", *pointerParam);
}
It just exits with an error code, it does nothing. If I try to printf *x inside the function, it does work so I know that part at least works.
Any help would be greatly appreciated!
There are multiple problems with the code as it is shown.
The main problem is probably that you misunderstand how emulation of pass-by-reference works in C.
For it to work you need to pass a pointer to the variable that should be set. This is done using the pointer-to operator &. You also need to dereference the pointer, to set the variable the pointer is pointing to.
Putting it together your program should look something like this (simplified):
void testFunction(int a,int b, int *x)
{
// Assign to where `x` is pointing
*x = a + b;
}
int main(void)
{
int n1 = 7;
int n2 = 90;
int result; // Where the result should be written
// Pass a pointer to the `result` variable, so the function can write to it
testFunction(n1, n2, &result);
}
I will show you a program that is no more than a set of printf() and your function. Maybe the program's output helps in showing these pointers, arrays and integers things.
The example
Consider these variables
int n[4] = {10, 20, -30, -40};
int v1 = 0;
int v2 = 0;
int* a_pointer = NULL;
int* is a pointer to an int, that's the meaning of the asterisk in the declaration. In this context the asterisk is called the dereference operator or the indirection operator. But the asterisk also is the multiplication operator in C. ;)
Now a_pointer points to nothing, the meaning of the NULL.
But a_pointer is there to hold an address of something, of an int. The way of getting such address of something is the address of operator, the &, that also has an alternate life as the bitwise and operator in C. Things of life.
In printf() the %p specifier shows an address. This
printf("\naddress of v1 is %p\n", &v1);
printf("address of v2 is %p\n", &v2);
printf("address of array n[0] is %p\n", n);
printf("address of array n[0] is %p\n", 1 + n);
printf("address of array n[0] is %p\n", 2 + n);
printf("address of array n[0] is %p\n\n", 3 + n);
shows (in a 32-bits compilation)
address of v1 is 008FFDA0
address of v2 is 008FFD9C
address of array n[0] is 008FFDA4
address of array n[1] is 008FFDA8
address of array n[2] is 008FFDAC
address of array n[3] is 008FFDB0
And you will see the reason the program prints these lines in the code below...
This line
a_pointer = &v1;
takes the address of v1 and assign it to the pointer a_pointer.
Now a_pointer is pointing to something, to v1, and you can use it in your function. These lines are equivalent
testFunction(n[0], n[3], &v1);
and
testFunction(n[0], n[3], a_pointer);
In these lines
testFunction(n[0], n[3], &v1);
printf("n[0] = %d, n[3] = %d, sum in v1 is %d\n", n[0], n[3], v1);
printf(
"p points to v1. value is %4d, address is %p\n\n", *a_pointer,
a_pointer);
you see the use of the pointer to access the value it points to, using the dereference operator in the printf().
Follow the program along to see a few uses of this.
In particular, see these lines
a_pointer = n + 3;
printf(
"\np points now to n[3]. value is %4d, address is %p\n",
*a_pointer, a_pointer);
to see the thing C is made for: address memory easily. n is int[4], an array of int. a_pointer is a pointer to int. And the language knows that when you write a_pointer = n + 3 that it needs to add to the address of n, an int[], the size of 3 int variables, and assign it to the pointer, so *a_pointer is n[3]and it is used to call testFunction() in
testFunction(n[1], n[2], n + 3);
program output
n[] is [10,20,-30,-40], v1 is 0 v2 is 0
address of v1 is 00CFFA9C
address of v2 is 00CFFA98
address of array n[0] is 00CFFAA0
address of array n[1] is 00CFFAA4
address of array n[2] is 00CFFAA8
address of array n[3] is 00CFFAAC
n[0] = 10, n[3] = -40, sum in v1 is -30
p points to v1. value is -30, address is 00CFFA9C
p now points to v2. value is 0, address is 00CFFA98
n[0] = 10, n[1] = 20, sum in v2 is 30
n[] is [10,20,-30,-40], v1 is -30 v2 is 30
p now points to v1. value is -30, address is 00CFFA9C
n[] is [10,20,-30,-40], v1 is -30 v2 is 30
now makes n[3] = n[1] + n[2] using testFunction()
n[] is [10,20,-30,-10], v1 is -30 v2 is 30
p points now to n[3]. value is -10, address is 00CFFAAC
the code
#include <stdio.h>
show(int[4], int, int);
void testFunction(int, int, int*);
int main(void)
{
int n[4] = {10, 20, -30, -40};
int v1 = 0;
int v2 = 0;
int* a_pointer = NULL;
show(n, v1, v2);
printf("\naddress of v1 is %p\n", &v1);
printf("address of v2 is %p\n", &v2);
printf("address of array n[0] is %p\n", n);
printf("address of array n[1] is %p\n", 1 + n);
printf("address of array n[2] is %p\n", 2 + n);
printf("address of array n[3] is %p\n\n", 3 + n);
a_pointer = &v1;
testFunction(n[0], n[3], &v1);
printf("n[0] = %d, n[3] = %d, sum in v1 is %d\n", n[0], n[3], v1);
printf(
"p points to v1. value is %4d, address is %p\n\n", *a_pointer,
a_pointer);
a_pointer = &v2;
printf(
"p now points to v2. value is %4d, address is %p\n", *a_pointer,
a_pointer);
testFunction(n[0], n[1], &v2);
printf("n[0] = %d, n[1] = %d, sum in v2 is %d\n", n[0], n[1], v2);
show(n, v1, v2);
a_pointer = &v1;
printf(
"\np now points to v1. value is %4d, address is %p\n", *a_pointer,
a_pointer);
show(n, v1, v2);
printf("\nnow makes n[3] = n[1] + n[2] using testFunction()\n");
testFunction(n[1], n[2], n + 3);
show(n, v1, v2);
a_pointer = n + 3;
printf(
"\np points now to n[3]. value is %4d, address is %p\n",
*a_pointer, a_pointer);
return 0;
};
show(int n[4], int v1, int v2)
{
printf(
"n[] is [%d,%d,%d,%d], v1 is %d v2 is %d\n", n[0], n[1], n[2],
n[3], v1, v2);
};
void testFunction(int a, int b, int* sum)
{
*sum = a + b;
return;
}
I will not go into religious discussions here, but you may find easier to understand the meaning of the declarions if you write
int* some_int = NULL;
instead of
int *some_int = NULL;
you declare a name, and the name is some_int. The compiler will tell you that some_int is int*, its type. The fact that *some_int is an int is a consequence of the application of an operator to a variable.
You lacked just to understand how pointers are managed, but you were almost correct:
/* this is almost correct, you could have just said: *x = a + b; */
void testFunction(int a,int b, int *x)
{
int c=a+b;
*x=c; /* the pointed to value is what we are assigning */
}
int main()
{
int n1=7;
int n2=90;
int result; /* vvvvvvv this is the important point */
testFunction(n1, n2, &result); /* you pass the address of result as the required pointer */
printf("Value of pointer is %d\n", result);
}

How to double deref in C?

Trying to double dereference and print them (TOP TWO ARE EXAMPLES):
printf ("a's value = %d \n", a) ;
printf ("a's address = %p \n", &a) ;
printf ("a_ptr_ptr deref'ed defer'ed =d% \n",
What would go after the \n", for a_ptr_ptr deref'ed defer'ed
If you want the address of the address of a, you're going to have to store a's address in a pointer variable, and take the address of that. But having done so, yes, you can double-dereference that pointer with **, and get a's value back. Something like this:
int a = 5;
int *ip = &a;
int **ipp = &ip;
printf("ipp = %p\n", ipp);
printf("*ipp = %p, ip = %p, &a = %p\n", *ipp, ip, &a);
printf("**ipp = %d, *ip = %d\n", **ipp, *ip);
Theoretically you can continue this as long as you like:
int ***ippp = &ipp;
int ****ipppp = &ippp;
int *****ippppp = &ipppp;
printf("*****ippppp = %d\n", *****ippppp);
But by now this is mostly a game; there's no practical use in a real C program for a 5-level pointer, and at some point (after 8 or 10 levels, I think) the compiler's allowed to say "All right, enough, game over!".

Same C pointer showing different values?

I'm running this program:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = &num;
char *pointChar = poinTer+1;
*pointChar = 'A';
printf("Size of Integer: %d\n", sizeof(int));
printf("Address: %d, Value: %d\n", poinTer, *poinTer);
printf("Address: %d, Value: %c\n", poinTer+1, *(poinTer+1));
printf("Address: %d, Value: %c\n", pointChar, *pointChar);
}
*pointChar and *(poinTer+1) should output same result but the output that I'm getting is different. *pointChar is not outputting any value:
Size of Integer: 4
Address: 1704004844, Value: 1025
Address: 1704004848, Value: A
Address: 1704004673, Value:
What's happening here?
When you perform + 1 on a pointer, it does not necessarily increase the memory address by 1. It increases it by sizeof(*ptr).
In this case, poinTer + 1 is equivalent to (char*)poinTer + sizeof(int). This actually makes dealing with arrays much easier.
The good old fashioned ptr[i] is syntactic sugar for *(ptr + i). So, if you have an array of 10 integers, ptr[4] will point to the 5th element rather than 4 bytes away from the base address (since integers are generally 4 or 8 bytes).
So what you've actually done is:
Create an int (num) on the stack and gave it the value 1025
Created a int*(poinTer) on the stack and assigned it the memory address of num
Incremented the pointer by sizeof(int) (which unintentionally points to a different memory address), then cast it to a char* and assigned it to a new pointer.
Assigned the byte pointed to at this new memory address the value 65 ('A').
This is probably what you wanted to do:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = &num;
char *pointChar = (char*)poinTer + 1;
*pointChar = 'A';
printf("Size of Integer: %d\n", sizeof(int));
printf("Address: %d, Value: %d\n", poinTer, *poinTer);
printf("Address: %d, Value: %c\n", (char*)poinTer + 1, *((char*)poinTer+1));
printf("Address: %d, Value: %c\n", pointChar, *pointChar);
}

Modify struct via a reference taking function

I want to assign the struct a to the struct b. Printing the address and the values of the array before and after function call it shows that during the function call the assignment works and both pointers point to the same struct address. However, after returning from the function the changes are reversed. Why?
typedef struct arrayA {
int a[3];
}arrayA;
void f(arrayA *a, arrayA *b){
a = b;
printf("address of a: %p\n", a);
printf("address of b: %p\n", b);
}
int main(int argc, char *argv[]) {
printf("------------ Array assignment test -----------------\n");
arrayA a = { { 0, 0, 0} };
arrayA b = { { 1, 1, 1} };
printf("address of a: %p\n", &a);
printf("address of b: %p\n", &b);
printf("a[0] : %d a[1] : %d\n", a.a[0], a.a[1]);
f(&a, &b);
printf("a[0] : %d a[1] : %d\n", a.a[0], a.a[1]);
printf("address of a: %p\n", &a);
printf("address of b: %p\n", &b);
printf("----------------------------------------------------\n");
return 0;
}
Prints
------------ Array assignment test -----------------
address of a: 0x7ffd3fc17b80
address of b: 0x7ffd3fc17b90
a[0] : 0 a[1] : 0
address of a: 0x7ffd3fc17b90
address of b: 0x7ffd3fc17b90
a[0] : 0 a[1] : 0
address of a: 0x7ffd3fc17b80
address of b: 0x7ffd3fc17b90
----------------------------------------------------
You are passing the pointers by value and expecting them to get modified. They will be modified within the function as there is a copy of the pointer (address) that is made local to the function. When the function returns the originals remain unchanged. (You could try to print the address of the local variables within the function to understand better.)
If you want to change the structs, you'll want to dereference the pointers:
void f(arrayA *a, arrayA *b){
*a = *b;
printf("address of a: %p\n", a);
printf("address of b: %p\n", b);
}
If you want to change the pointers themselves, you'll need an extra indirection:
void f(arrayA **a, arrayA **b){ // Note the ** here
*a = *b;
printf("address of a: %p\n", a);
printf("address of b: %p\n", b);
}
However, after returning from the function the changes are reversed. Why?
Your f() function really just change the pointer inside it, and those pointer changes are not reserved after the function.
You can copy struct by pass-by-pointer:
void f(arrayA *a, arrayA *b){
*a = *b;
}
That will ensure you can copy struct in main() via
f(&a, &b);
As all you need is copy struct, there is no need to print out the addresses at all. In case you do need to debug the address, you should convert to (void *) to avoid all the warnings with printf("%p")

int pointer expressions

#include<stdio.h>
#include<stdlib.h>
int main ()
{
int a[]={0,1,2,3,4};
int *p[]={a,a+1,a+2,a+3,a+4};
int **ptr=p;
ptr++;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
*ptr++;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
*++ptr;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
++*ptr;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
return 0;
}
The answer for this program is
1 1 1
2 2 2
3 3 3
3 4 4
with gcc.But why is the output for the first printf giving 1 1 1 shouldn't it be 4 4 1?
lets say if p=6004 and and ptr would be 6004 and ptr++ would be 6008.then ptr-p should give 4.pls correct me.thanks..
The result of pointer arithmetic is not exactly the result of their address arithmetic. The output should be ((address of ptr) - (address of p)) / (sizeof(pointed_type))
For example:
int a[] = {0,1,2,3,4};
int *p=a;
int *p2 = p+1;
printf("%d",p2-p) // will print 1
I modified it a little to be certain. The point here is that subtracting pointer returns the number of units i.e. address / size of pointer, not plain difference of address locations.
printf("ptr before %p\n", ptr);
ptr++;
printf("ptr after %p and p %p\n", ptr, p);
printf("%ld %ld %d\n",ptr-p,*ptr-a,**ptr);
On my 64 bit machine, the printed addresses are 8 locations apart with just a single ++. On a 32 bit machine this would be 4. But still the arithmetic difference would return 1.

Resources