how pointer assignment and increment is working in below example - c

I am learning the pointers in C. I am little confused about how below program is working
int main()
{
int x=30, *y, *z;
y=&x;
z=y;
*y++=*z++;
x++;
printf("x=%d, y=%p, z=%p\n", x, y, z);
return 0;
}
output is
x=31, y=0x7ffd6c3e1e70, z=0x7ffd6c3e1e70
y and z are pointing to the next integer address of variable x.
I am not able to understand how this line is working
*y++=*z++;
can someone please explain me how this one line is understood by C?

*y++=*z++; actually means
*y = *z;
y += 1*(sizeof(int)); //because int pointers are incremented by 4bytes each time
z += 1*(sizeof(int)); //because int pointers are incremented by 4bytes each time
So pointed value does not affected, pointers are incremented by one.

Related

New to pointers in C

In the following code I would like to understand better what is happening with int *z = malloc(sizeof(int);
To me that creates a pointer to an int. Then *z gets the sum of the value that x points to (2) and the value that y points to (4).
Now *z = 6. Does that mean *z does not point to anything? It just stores an int? I thought *z was a pointer and a pointer is an address? Thank you for any help understanding.
int *add(int *x, int *y)
{
int *z = malloc(sizeof(int));
*z = (*x) + (*y);
return z;
}
int main(void)
{
int a = 2;
int b = 4;
int *ptr = add(&a, &b);
printf("sum = %i\n", *ptr);
}
Now *z = 6. Does that mean *z does not point to anything? It just stores an int? I thought *z was a pointer and a pointer is an address? Thank you for any help understanding.
You are correct with *z = 6 however you are wrong with how this happens.
z is a pointer and so it point somewhere into the memory. Earlier in your program, with int *z = malloc(sizeof(int)); you have allocated a space the z points to.
Then when you did *z = (*x) + (*y); you've basically put the result of the addition into that allocated space.
z still points to that space (because it is a pointer). *z is called dereferencing and has a meaning of reaching directly for the value the pointer points to.
In other words: the 6 is stored in a place the z points to and *z is a way to grab that value.
*z = 6 assigns 6 to the location pointed at by ptr. That's what a pointer does, it points to things, but in order to put a value at where it's pointing as opposed to changing the pointer you need to de-reference with the * operator.1
Imagine your memory as, conceptually, a number of bytes each of which has a number. A pointer to an int represents a particular location in memory which is presumed to hold an int, or 4 bytes worth of data.
*z = 6 means "put an integer value of 6 in the memory location described by z", which translates into machine instructions that are largely the same.
z absolutely does not "store an int", it stores a location. That location may exist, or may be NULL, or may be invalid. There's no guarantees unless you've checked your code carefully to ensure the pointer is valid. That's your responsibility as a programmer.
That's also why pointers can be tricky and frustrating. They introduce indirection in your code.
1 In C pointers are also largely interchangeable with arrays so you can do z[0] = 6, though as z only points to a single int, any index other than 0 is invalid.
int *z = malloc(sizeof(int));
this will envoke a system call for allocating one integer on the heap. z is the address of this integer return from malloc (if malloc fails to allocate z will be null)
z is a pointer to buffer allocated on the heap (if malloc success). in your case this buffer hold one integer so its a pointer to this integer.
see malloc description in man pages. malloc_man_pages
*z = (*x) + (*y);
you are right. you are assigning the value that sets in the address x and the value that sets in the address y to the place that z points to.
you dont check the return vale from malloc and this is a very bad thing. always check if malloc successd! see below. maybe you need to check the pointers that you get in x and y ?! (thats up to you, but i recommend to check).
int* add(int *x, int *y)
{
int *z = NULL;
if(x && y)
{
z = malloc(sizeof(int));
if(z)
{
*z = (*x) + (*y);
}
}
return z;
}

Understanding pointers in C using example code

I am learning pointers in C, so I am looking at one example. I tried to add comments to understand what is going on. Is the following code correct? In other words, do my comments describe the operation correctly?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(){
int x, y;
int *p1, *p2;
x=-42;
y=163;
p1=&x; //pointer 1 points to the address of x
p2=&y; //pointer 2 points to the address of y
*p1=17; //this just made x=17 because it says that the value at the address where p1 points should be 17
p1=p2; //this just made pointer 1 point at the same place as pointer 2, which means that p1 now points at y
p2=&x; //this just made pointer 2 point at the address of x
//NOW WE HAVE: p1 points at y, p2 points at x, y=17 because of p1
*p1=*p2; //now x=17 as well as y (because the value at the place p2 points, which is x, just became 17)
printf("x=%d, \ny=%d\n", x, y);
return 0;
}
"Check the debugger", for sure. You can also just copy your printf statement after each time you set a value to check, since you're just learning, but this isn't good long-term practice.
I'm not sure if you've quite got the concept and just made a typo mixing up x and y, or if you're making an incorrect assumption, but yes, in your comments:
//NOW WE HAVE: p1 points at y, p2 points at x, y=17 because of p1
you have the location of p1 and p2 correct at this point, but y has not received an assignment since you gave it the value of 163 initially. Assignments to *p1 will affect y, but only after the p1=p2 line.
At the point of this comment, x=17, because of the *p1=17 line a few line up. y is unchanged from the initial assignment.
*p1=*p2; //now x=17 as well as y (because the value at the place p2 points, which is x, just became 17)
y becomes 17 here, as *p1 (which is now y) is assigned the value in *p2, which, as you state, is x.

What is the difference between referencing pointers in a function

I'm creating a function which modifies a variable so it can be used by the function referencing it (parent function?).
Is there a difference between using '&x' compared to using 'z' in the code below?
void changeX(int *p);
int main(void) {
int x = 10;
printf("%d\n",x);
int *z = &x;
changeX(z);
printf("%d\n",x);
// or
changeX(&x);
printf("%d\n",x);
return 0;
}
void changeX(int *p){
*p = *p + *p;
}
wildplasser made a good point, updated to show where I have gotten each value in the output.
Output is:
10
20
40
Both produce the same outcome (change x in the same way), but is there a non-obvious difference between them?
Thanks for the answers in the comments. It makes sense to me now.
The first call initializes the parameter from the argument z, i.e., the value of the argument is the value of the pointer z, which was initialized to be &x, a pointer value that points to the object x. The second call initializes the parameter from the argument &x, which is a pointer value that points to the object x. There is no functional difference between the two calls. In both cases, the parameter p in the function will have the exact same value, a pointer value that points to x, the only difference is where that value came from at the point where function was called…

C - Increment and decrement pointer, then retrieve value

The following code outputs y as a massive integer, not 15. I don't understand why. I know the -- and ++ operators come before the * operator, so it should work.
What the follwing code is trying to say.
/*
Create a variable, set to 15.
Create a pointer to that variable.
Increment the pointer, into undefined memory space.
Decrement the pointer back where it was,
then return the value of what is there,
and save it into the variable y.
Print y.
*/
int main()
{
int x = 15;
int *test = &x;
test++;
int y = *test--;
printf("%d\n", y);
return 0;
}
If instead, I change the code to the following:
int main()
{
int x = 15;
int *test = &x;
test++;
test--;
printf("%d\n", *test);
return 0;
}
That code outputs 15. Why?
The difference is between x++ and ++x, post- and pre-increment of a pointer.
When ++ is after x, the old value is used prior to the increment
When ++ is before x, the new value is used after the increment.
This will work:
int y = *(--test);
Although parentheses are not necessary, it is a good idea to use them for clarity.

understanding pointers in functions (referring values)

int func (int a, int b, int *c);
int main()
{
int res, x, y, z; //int res, x, y, *z;
printf("enter x \n");
scanf("%i", &x);
printf("enter y \n");
scanf("%i", &y);
res = func(x, y, &z); //res = func(x, y, z);
printf("result addition: %i, result multiplication %i \n", res, *z);
return 0;
}
int func (int a, int b, int *c)
{
int result;
result = a +b;
*c = a*b; //(1) alternative:d=a*b
// c=&d
return result;
}
My problem is, that i don't understand, why this code doesn't work when i write it as i like i did in the comments (//) . Compiler warns me, that z is not initialised, but why isn't that a problem in the working version?
Another thing i don't understand is, why it's correct to refer pointer a value like i did it in (1) but it's wrong in the following code:
int main()
{
int a, *c, *d;
scanf("%i", &a);
*c=a; //wrong
d=&a; //correct
return 0;
}
Compiler warns me, that z is not initialised, but why isn't that a problem in the working version?
The compiler warns you about z being uninitialized because you're passing it by value. And what you're passing is an uninitialized value (which is basically garbage).
It doesn't warn you when you pass the address of z because there's nothing wrong with passing the address of a variable to a pointer. The compiler doesn't check whether you're going to dereference c and use the uninitialized value of z. The compiler's just not that "smart". It assumes you'll do the right thing and just assign z a value by dereferencing c (which you indeed did).
why it's correct to refer pointer a value like i did it in (1) but it's wrong in the following code
As for your 2nd question, the first example works because the parameters of the functions get initialized to whatever values you called the function with.
The 2nd example doesn't work because you're using uninitialized local variables.
At the point where a variable is declared, it comes into existence at some memory location that can be retrieved with &, whereas (if you don't initialize it) the contents of that location is uninitialized. When z is an int, &z is a well-defined pointer because it is the address of a variable, not the contents of one. When z is an int *, z's content is itself a pointer, but it's not initialized; hence the warning (and most likely, your program will crash when scanf() attempts to write to an arbitrary memory location).
your question implies that you have no knowledge about pointers, I suggest you read about them first,
a pointer points to a variable, when you do
*c = a
you are trying to assign a value to the variable pointed to by c with the indirection operator '*',
the problem is that c is not pointing to anything in your code.
in the second one
d = &a;
you make the pointer d point to a. In other words you assign d the address of a. You really should read about pointers first otherwise, whatever we say here will not make sense to you.

Resources