Pointer initialization with an arbitrary number - c

{
int *p=12;
printf("%p",p);
printf("\n%d",p);
}
OUTPUT:
0000000C
12
Question: So is p assigned the address 0x0000000C?
{
int *p=12;
*p=22;
}
But this one doesn't run. So what's actually happening?

int *p=12;
This declares a pointer and sets the address to which it points to 12.
*p=22;
This de-references the pointer and writes 22 to the int at that memory address 12. Since you did not allocate any memory and just set the pointer to point at a random address, it results in a runtime error.
What is confusing you is that both pieces of code contain *p=.... However, the first assignment is to the pointer, and the second assignment is to the pointee. This is just one of those notational overloadings that you have to get used to when programming in C.

Both cases have undefined behavior.
The behavior of the first example is undefined, as you use an invalid pointer.
The second example is worst, as you derefernce a pointer with invalid address.
int *p=12; // set the address 12 to the int pointer called p
*p=22; // set the value 22 to the address 12 (invalid address)

Related

Double Pointer and Local Scope Confusion

I am taking a c programming course on Udemy and am quite confused when passing a double pointer into a function. In the example, the instructor passes the address of a pointer as an argument to a function. Then, he de-references that double pointer parameter in the function and sets it equal to the address of a local variable (a).
#include <stdio.h>
#include <malloc.h>
void foo(int **temp_ptr)
{
int a = 5;
*temp_ptr = &a;
}
int main()
{
int *ptr = NULL;
ptr = (int*) malloc(sizeof(int));
*ptr = 10;
foo(&ptr);
printf("%d\n", *ptr);
return 0;
}
So, what we are doing here is changing the value of ptr to hold the address of a. Then, when we de-reference ptr, it should display the value of 5 and not 10, since we changed the value of ptr to hold the address of a.
This is indeed correct: it displays 5 and not 10.
However, what doesn't make sense here is that the variable a is in the local scope of the foo function. When we declare a, the memory allocated is put onto the stack frame; thus, when leaving the local scope of the function that memory is deleted and the frame is popped off of the stack. How can we still access that variable a with the ptr variable in the main function? Shouldn't that memory be completely wiped out?
Then, when we de-reference ptr, it should display the value of 5
Should is incorrect. printf("%d\n", *ptr); is undefined behavior (UB) as the address stored in ptr is invalid with the return of foo(&ptr);.
Output may print 5, may print 42, may crash. It is UB.
... correct that the memory of the stack should be completely wiped out
No. There is not specified wiping of memory. The result is UB.
But sometimes undefined behavior works?
"undefined behavior" is undefined. Even if it "works" today, it may not "work" tomorrow.
When we declare a, the memory allocated is put onto the stack frame; thus, when leaving the local scope of the function that memory is deleted and the frame is popped off of the stack.
This assumes an underling code model that is not specified by C. Other real possibilities exist.
How can we still access that variable a with the ptr variable in the main function?
As is, no defined way. Alternatively keep the address of a valid by making a static.
In Foo function, we are updating the address of our pointer. int a declared in foo function will be stored at some memory location. Now, we are assigning that location to our ptr(which is okay, ptr can point to any memory location of type int). But the issue is the value at that location is not in our control and this location can be used for any other purpose which may update the value at that location.
It means that our pointer is now pointing to location that may be updated by any other source.

What is the address of a pointer in C?

int main()
{
int *p;
printf("%p \n", &p);
printf("%p \n", p);
return 0;
}
By executing this code I am receiving the following output:
0x16b77f710
0x104683f4c
I expected to get the same memory address, because the &p id not referenced to any other variable.
Why i am getting two different memory address?
Thanks,
The pointer is a normal object having (in your case type of int *). It cant point to itself because the type of such pointer would have to be int **
*image stolen from internet.
A pointer is a variable like any other. It has an address, which is typically the address in memory where that variable sits.
Like any other variable, a pointer variable also has some data in it. For a pointer variable, that data is the address of some other variable, the variable at which the pointer points.
The address of a variable, and the contents of a variable, are two totally different things. They are almost never equal.
Try this program, in which I give your variable p something to point to:
int main()
{
int i = 5;
int *p = &i;
printf("p: %p, p's address: %p\n", p, &p);
printf("i: %d, i's address: %p\n", i, &i);
}
You should notice two things:
As in your first program, "p" and "p's address" will be different.
Whatever value you see for "p", it will be the same as "i's address".
The reason is that a pointer, when declared, does not point to itself by default. Simplified you can imagine it in such a way that a pointer occupies 2 memory cells. 1 memory cell has the virtual address where the pointer itself is located (&p in your case), the 2nd memory cell contains the virtual address where the pointer points to (p in your case).
Since memory cells retain their value when they are deallocated, the cell containing the destination address of your pointer still contains an obsolete value from another, already completed process.
You would have the same phenomenon if you declare a new integer variable and then print its value with printf, you will see that there will already be some number in the new variable that will appear completely random. This is also due to the fact that there is still an obsolete value in the corresponding memory cell.
Let assume there is random memory block for just understanding name it a. Now assume that p is pointing to that memory block.
&p returns the address of memory block where p is present.
p returns the address of memory block(&a) to the variable/memory block(a) which p is pointing.
So of course it will give different memory addresses.
I expected to get the same memory address, because the &p id not referenced to any other variable.
Pointer variables do not automatically point to themselves; if you don't explicitly initialize them, then their initial value will be indeterminate (or NULL, depending on how they are declared).
There's nothing magic about pointer variables - like any other scalar, they store some kind of value; it's just that in their case, that value is an address of another object.
If you really want p to store its own address, you'll have to do something like
p = (int *) &p;
The cast is necessary because the type of the expression &p is int **, and you can't assign a pointer value of one type to a variable of a different pointer type. But, pointers to different types are not guaranteed to have the same size, representation, or alignment. On modern commodity hardware like x86 you can probably count on int * and int ** having the same size and representation, just be aware that doesn't have to be the case everywhere.

What is the difference between derefencing and assigning the address of a variable to pointer variable in C?

See the two codes below!
int main() {
int a = 12;
int *p;
*p = a;
}
and the this code,
int main() {
int a = 12;
int *p;
p = &a;
}
In the first piece of code dereferenced the pointer as this *p = a, and in the second piece of code, the address of variabe a is set to the pointer variable.
My question is what is the difference between both pieces of codes?
In your first piece of code:
int main() {
int a = 12;
int *p;
*p = a;
}
you have a serious case of undefined behaviour because, what you are trying to do is assign the value of a to the int variable that p currently points to. However, p has not been assigned an 'address', so it will have an arbitrary - and invalid - value! Some compilers may initialise p to zero (or NULL) but that is still an invalid address (on most systems).
Your second code snippet is 'sound' but, as it stands, doesn't actually achieve anything:
int main() {
int a = 12;
int *p;
p = &a;
}
Here, you are assigning a value (i.e. an address) to your pointer variable, p; in this case, p now points to the a variable (that is, it's value is the address of a).
So, if you appended code like this (to the end of your second snippet):
*p = 42;
and then printed out the value of a, you would see that its value has been changed from the initially-given 12 to 42.
Feel free to ask for further clarification and/or explanation.
Declaring *p and a is reserving some space in memory, for a pointer in first case, for what a is in the 2nd case (an int).
In these both cases, their values are not initialized if you don't put anything in it. That doesn't mean there is nothing in it, as that is not possible. It means their values are undetermined, kind of "random" ; the loader just put the code/data in memory when requested, and the space occupied by p, and the one occupied by a, are both whatever the memory had at the time of loading (could be also at time of compilation, but anyway, undetermined).
So you take a big risk in doing *p = a in the 1st case, since you ask the processeur to take the bytes "inside" a and store them wherever p points at. Could be within the bounds of your data segments, in the stack, somewhere it won't cause an immediate problem/crash, but the chances are, it's very likely that won't be ok!
This is why this issue is said to cause "Undefined Behavior" (UB).
When you initialized a pointer you can use *p to access at the value of pointer of the pointed variable and not the address of the pointed variable but it's not possible to affect value like that (with *p=a). Because you try to affect a value without adress of variable.
The second code is right use p = &a
The first one is bad:
int main() {
int a = 12;
int *p;
*p = a;
}
It means: put the value of variable a into location, pointed by pointer p. But what the p points? probably nothing (NULL) or any random address. In best case, it can make execution error like access violation or segmentation fault. In worst case, it can overwrite any existing value of totally unknown variable, resulting in problems, which are very hard to investigate.
The second one is OK.
int main() {
int a = 12;
int *p;
p = &a;
}
It means: get the pointer to (existing) variable a and assign it to pointer p. So, this will work OK.
What is the difference between dereferencing and assigning the address of a variable to pointer variable in C?
The latter is the premise for the first. They are separate steps to achieve the benefit of pointer dereferencing.
For the the explanation for where the difference between those are, we have to look what these guys are separately:
What is dereferencing the pointer?
First we need to look what a reference is. A reference is f.e. an identifier for an object. We could say "Variable a stands for the value of 12." - thus, a is a reference to the value of 12.
The identifier of an object is a reference for the value stored within.
The same goes for pointers. pointers are just like usual objects, they store a value inside, thus they refer to the stored values in them.
"Dereferencing" is when we "disable" this connection to the usual value within and use the identifier of p to access/refer to a different value than the value stored in p.
"Dereferencing a pointer" means simply, you use the pointer to access the value stored in another object, f.e. 12 in a instead through its own identifier of a.
To dereference the pointer the * dereference operator needs to precede the pointer variable, like *p.
What is assigning the address of a variable to a pointer?
We are achieving the things stated in "What is dereferencing a pointer?", by giving the pointer an address of another object as its value, in analogy like we assign a value to a usual variable.
But as opposed to usual object initializations/assignments, for this we need to use the & ampersand operator, preceding the variable, whose value the pointer shall point to and the * dereference operator, preceding the pointer, has to be omitted, like:
p = &a;
Therafter, The pointer "points" to the address the desired value is stored at.
Steps to dereferencing a pointer properly:
First thing to do is to declare a pointer, like:
int *p;
In this case, we declare a pointer variable of p which points to an object of type int.
Second step is to initialize the pointer with an address value of an object of type int:
int a = 12;
p = &a; //Here we assign the address of `a` to p, not the value of 12.
Note: If you want the address value of an object, like a usual variable, you need to use the unary operator of &, preceding the object.
If you have done these steps, you are finally be able to access the value of the object the pointer points to, by using the *operator, preceding the pointer object:
*p = a;
My question is what is the difference between both pieces of codes?
The difference is simply as that, that the first piece of code:
int main() {
int a = 12;
int *p;
*p = a;
}
is invalid for addressing an object by dereferencing a pointer. You cannot assign a value to the pointer´s dereference, if there isn´t made one reference before to which the pointer do refer to.
Thus, your assumption of:
In the first piece of code I dereferenced the pointer as this *p = a...
is incorrect.
You do not be able to dereference the pointer at all in the proper way with *p = a in this case, because the pointer p doesn´t has any reference, to which you are be able to dereference the pointer correctly to.
In fact, you are assigning the value of a with the statement of *p = a somewhere into the Nirwana of your memory.
Normally, the compiler shall never pass this through without an error.
If he does and you later want to use the value, which you think you´d assigned properly by using the pointer, like printf("%d",*p) you should get a Segmentation fault (core dumped).

C programming , pointers run time error

I coded something like the following code,and I was able to assign a value to the new address after increasing it but was not able to print this value run time error, Also after assigning a value to the location this pointer pointing to, pointer value changed to be 14. Anyone has an idea of what's going on ?
Why the pointer value itself changed to 14 after assigning value to the location itself ?
I did not get any error after increasing the pointer value too !
#include <stdio.h>
int main()
{
int x = 10;
int *ptr = &x;
printf("%x\n",ptr); // ptr value
ptr++; //No ERROR !!
printf("%x\n",ptr); //ptr value +4 bytes no error!!!
*ptr = 20;
printf("%x\n",ptr); //ptr=14
printf("%x\n",*ptr); // run time error happens here only
return 0;
}
This is undefined behavior. When you incremented the pointer variable then it was pointing to one past the variable x (4 Bytes past in your system). But then you dereference it. First of all the memory you made change to is not allocated by you. And also it is not a location that is already allocated (like part of an array etc). It is Undefined behavior to access it.
And again you can assign it to any possible address. But dereferencing it would be undefined behavior in case the memory address it points to is invalid.
From standard 6.3.2.3
The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator; if it points to an
object, the result is an lvalue designating the object. If the operand
has type ''pointer to type'', the result has type type. If an
invalid value has been assigned to the pointer, the behavior of the
unary * operator is undefined
When you do ptr++, it points "one element" past x. This is allowed, because x in this case is treated as an array of size 1, and a pointer is allowed to point one element past the end of an array. You can also subsequently print the value of that pointer with no problem.
What you can't do however is dereference a pointer to one element past the end. That invokes undefined behavior. In this case that behavior manifested as the pointer having an unexpected value and a subsequent crash.
That being said, here's what probably happened.
ptr was most likely placed right after x in memory, so after doing ptr++, ptr was pointing to itself. So *ptr = 20; had the effect of of setting ptr to 20. The value 14 that was printed is in hex, which is the same as 20 decimal. This explains the value that was printed.
Then you tried to print *ptr, which in this case says "print the int value at address 0x14". That is most likely not a valid address, so attempting to read it caused a crash.
You can't however depend on this behavior. You could add an extra printf or compile with different optimization settings and the observed behavior would change.

How does a pointer to the constant pointer of the first element of an array work?

I wanted to test if I could change the constant pointer that points to the first element of an array in C. While testing I got some strange output that I don't understand:
//Constant pointer to pointer to constant value
void test(int const * * const a) {
//printf("%d", **a); //Program crashes (2)
(*a)++;
}
int main()
{
int a[5] = { 1,2,3,4,5 };
test(&a);
printf("%d", *a); //Prints 5 as output (1)
return 0;
}
I expected the compiler to give an error when I try to compile (*a)++ but instead I can run the code, but when I try to print the element I get a strange value (1).
Then I wanted to print out the value (2) of the first element of the array. When I tried this, the program crashes.
By doing &a you are making a pointer to an array (int (*)[]).
Then when this pointer to array is passed to the test function, it's converted to a pointer to a pointer(int **);
Then (*a)++; is UB.
1. So why 5?
On modern implementation of C like GCC, pointer to a array has the same numerical value as the beginning of the array, so is the address value when the array decays to a pointer: they all are the beginning address of the array.
So, in test, int **a points to the beginning of the array, (*a)++ deferences the pointer as int * and increment the pointer by 1 int element, which is usually implemented as adding the sizeof(int) to the numerical value of the pointer.
Then, 1+sizeof(int) gives you 5.
2. Why it crashed in the second case?
Assuming you are using a 32bit x86 machine, or some machine whose pointer type has the same size as int type, then *a equal to 1. Then further dereferencing the pointer at a memory address at 1 usually gives you a segfault.
The program crashes at the printf because test assumes that when it dereferences a the resulting object is a pointer. If it were one and contained a valid address, the second dereferencing would yield an int object. Alas, a contains the address of the array, which is numerically the address of its first element. The 4 or 8 bytes there are considered an address (because test thinks that *a is a pointer) and the code then tries to access the memory at address 1 in order to print the int value assumed at that address. The address is invalid though, so the program crashes.
Now that we have established that the program considers the data at the beginning of the array a pointer to int, we know what (*a)++ does: it increments the value there by sizeof(int) so that the "pointer" point to the next int "element". I guess an int on your machine is 4 bytes long because 1+4=5, which is printed.
This code is illegal in C, you should get a compiler diagnostic. (If not, turn up your warning level). The results of running any executable produced are meaningless.
The code is illegal because int (*)[5] does not implicitly convert to int const **.
the constant pointer that points to the first element of an array in C
There is no such thing. You misunderstand what arrays are. Arrays are a series of contiguous elements. int a[5] is like int a; except that there are 5 ints instead of 1.
int a; and int a[1]; cause identical memory layout. The only difference is the syntax used to access that memory.

Resources