Pointers questions and confusion - c

This may be simple but it confuses me.
int x;
int *p = NULL;
int *q = &x;
What happens when
q = p; // Address where q points to equals NULL .
&x = q; // I don't think this is possible .
*q = 7; // Value of memory where q is pointing to is 7?
*q = &x // That's just placing the address of x into memory where q points to right?
x = NULL;

q = p;
Yes. q now points to NULL, just like p.
&x = q;
Not legal. You cannot reassign the address of a variable.
*q = 7;
Yes, sets the memory of the address where q is pointing to 7. If q points to NULL then this will cause an error.
*q = &x;
Not legal, q points to an integer, so you cannot assign an address to it. This is legal, as there is an implicit cast from int* (&x) to int (*q), but not very safe. In C++, it is just a plain error. You are right in saying that it places the address of x (cast to an int) into the memory pointed to by q.

Adding to peters explanation
*q=&x
this becomes legal at *q=(int)&x .However on a 32 bit OS its good to write *q=(long)&x.
Note:Some Compilers wont give you an error on *q=&x
x = NULL;
x will become 0;

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;
}

Why is this function not incrementing my variable in c?

So just experimenting with pointers in C.
void inc(int *p){
++(*p);
}
int main(){
int x = 0;
int *p;
*p = x;
inc(p);
printf("x = %i",x);
}
Why is this printing "x = 0" instead of "x = 1"?
Here's your error:
*p = x;
You're dereferencing p, which is unassigned, and giving it the current value of x. So x isn't changed because you didn't pass a pointer to x to your function, and dereferencing an uninitialized pointer invokes undefined behavior.
You instead want to assign the address of x to p:
p = &x;
Alternately, you can remove p entirely and just pass the address of x to inc:
inc(&x);
Because you don't set p to the address of x
Use
p = &x;
instead of
*p = x;
With *p = x you cause undefined behaviour because p has indeterminate value and points *somewhere*. But you don't know where it points and with *p = x you write the value of x to that memory location.
You need to assign the address of x to p. As mentioned in the other answers you might just want to pass in inc(&x);. No need to declare a variable and waste it like that.

How pointer increment works

int main(void)
{
int n1 = 2, n2 = 5;
int *p = &n1, *q = &n2;
*p = *(q++);
printf("%d,%d", *p, *q);
return 0;
}
output= 5,5
Why the value of *q is 5 it should have some garbage value?
int main(void)
{
int n1 = 2, n2 = 5;
int *p = &n1, *q = &n2;
*p = *(++q);
printf("%d,%d", *p, *q);
return 0;
}
output= 2,2
And how is this happening?
Can anyone explain how precedence rule works in pointers?
*p = *(q++); is (more or less) equivalent to *p = *q; q++;, so p is fine. q++ will be evaluated, yielding the old value of q (i.e. the value pre-increment). What you're seeing there is the expected behavior.
You do have undefined behavior in the deference of q in the printf call though since q no longer points at memory you own at that point. A million different things could be causing that (e.g. last time the memory was allocated, maybe a 5 was there, the compiler is being too nice and trying to help you, etc), but you cannot and should not depend on this behavior. Doing so is dangerous, and this program would likely crash or output nonsense on many compilers/operating systems/hardware.
Why the value of *q is 5 it should have some garbage value?
It is due to the postfix incrementation in *(q++) which acts after the pointer dereference and the assignment to *p.
So, the current value of the address pointed by *q is assigned to *p, and then q is incremented to a "garbage value".
This strange result in printing 5,5 is undefined behaviour.

initialized the value of a pointer in declaring process

something in the pointer confuse me
to declare a pointer to int and then define it
int *p, a;
p = &a;
a = 3;
it can be changed into
int a = 3;
int *p = &a;
I'm confused in the latter case. Isn't the value of *p is the value of the object which p point to ( the value of a in this example) so why in the former case it's
int *p = &a;
which is the address of a but not the value of a. Shouldn't it be
int p = &a
in order to state that p is the pointer and the address it point to is the address of the object a
Additionally, I see in some case there is (int*) p. Does it have any different to normal declaration?
* in declaration
int *p = &a;
is not an indirection operator. It just inform the compiler that p is a pointer type. * acts a dereferencing operator only when it appears in a statement. This means that *p in int *p = &a; is not same as *p as an alias of a.

Does ptr = &a and *ptr = a mean the same?

In the book it explains:
ptr = &a /* set ptr to point to a */
*ptr = a /* '*' on left:set what ptr points to */
They seem the same to me, aren't they?
No. The first one changes the pointer (it now points at a). The second one changes the thing that the pointer is pointing at.
Consider:
int a = 5;
int b = 6;
int *ptr = &b;
if (first_version) {
ptr = &a;
// The value of a and b haven't changed.
// ptr now points at a instead of b
}
else {
*ptr = a;
// The value of b is now 5
// ptr still points at b
}
Well, no. But to explain the similar behaviour, Adding to Oli Charlesworth's answer:
Consider:
int a = 5;
int* ptr = new int;
if(first_version) {
ptr = &a;
//ptr points to 5 (using a accesses the same memory location)
} else {
*ptr = a;
//ptr points to 5 at a different memory location
//if you change a now, *ptr does not change
}
edit: sorry for using new (c++ not c) but the pointer thing does not change.
No, in ptr = &a you are storing the address of variable 'a' in variable 'ptr'
i.e., something like ptr=0xef1f23.
in *ptr = a you are storing the value of variable 'a' in pointer variable '*ptr'
i.e., something like *ptr=5.
Both are not same.
If u modify the value of a = 10. Then print again *ptr. It will print only 5. not 10.
*ptr = a; //Just copies the value of a to the location where ptr is pointing.
ptr = &a; //Making the ptr to point the a
*ptr=&a C++ compiler will genrate error becoz u r going to assign addres to adres
ptr=&a,this is true here ptr working like variable and &a is a addres of a which contain some value
check and try
int *ptr,a=10;
ptr=&a;output=10;
*ptr=&a signifies that our pointer is pointing towards address of the variable a
while
*ptr=a signifies that our pointer is pointing towards value a
*ptr = &a is not technically correct.
int *ptr = &a; is correct ..... Way (i)
(or)
int *ptr;
ptr = &a; is correct ..........Way (ii)
Here *ptr is a pointer to integer datatype.
int *ptr;
*ptr = a; This means ptr becomes a NULL pointer [i.e. it does not point to any memory location]. *ptr holds the value of a.

Resources