add local variable and pointer variable - c

I'm a beginner in C language.
I'm practicing several codes on my own, while doing I came across this algo.
Below is the code.
#include <stdio.h>
int main() {
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a);
int *p;
printf("value of p = %d\n", p);
p = 2;
printf("value of p = %d\n", p);
a = a+p;
printf("value of addition =%d\n", a);
return 0;
}
**OUTPUT**
value of a = 1
address of a = 947268620
value of p = 947268880
value of p = 2
value of addition =6
Why I'm getting 6 instead of 3,
is there anything I'm missing on result

because you're not setting the value of the address p is pointing to to 2, you're assigning/pointing the variable int *p to the value 2 in memory, which is not memory you should be accessing. Instead, you need to point p to memory you have access to (a variable or dynamically allocated memory) and dereference the pointer using *p = 2 which accesses the value that p is pointing to. Your code should instead look like this
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a);
int _p = 0;
int *p = &_p;
printf("value of p = %d\n", *p);
*p = 2;
printf("value of p = %d\n", *p);
a = a+*p;
printf("value of addition =%d\n", a);

One has to "walk right past" the compiler warnings about that code.
Below is the same code with coercive casting to silence some of the warnings. An additional calculation and print statement should make obvious how the compiler deals differently with the values of pointers (memory addresses) and the values of integers.
#include <stdio.h>
int main() {
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a); // incorrect format spec for printing address
int *p;
printf("value of p = %d\n", p); // uninitialised and undefined behaviour
p = (int*)2; // coercive casting integer to pointer-to-integer
printf("value of p = %d\n", p); // incorrect format spec for a memory address
a = (int)(a + p); // coercive casting address to integer
printf("value of addition =%d\n", a);
// ADDED these statements
a = 1; // restore value of a
a = a + (int)p; // coercive casting address to integer
printf("value of addition =%d\n", a);
return 0;
}
value of a = 1
address of a = 1703728
value of p = 1
value of p = 2
value of addition =6
value of addition =3 <== was this the expected result?
C will try to do its best with explicit program statements.
"Garbage in, garbage out."
Write correct code, not 'cute' code.

Thanks for your response Awayy. Helpful.
I got the output I needed. But the thing I need to know is, in what logic
the line a = a+p; gave 6 as result in my code.
As u said I'm assigning 2 as address to p(which is p = 0x2).
So, when the addition happens a = 1 and p = 0x2 which has a random value that we don't know that is because I'm not assigning a particular address to the pointer variable p. It results 6 I'm I right.

Related

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!".

pointer to pointer address

I have a question about pointer to pointer.
Here's my code
#include <stdio.h>
void main()
{
int num=10;
int *numPtr1;
int **numPtr2;
numPtr1 = &num;
numPtr2 = &numPtr1;
printf("%d\n", num);
printf("%d\n", *numPtr1);
printf("%d\n", **numPtr2);
printf("%p\n", &num);
printf("%p\n", numPtr1);
printf("%p", numPtr2);
}
Why numPtr2's address is not the same with numPtr1, numPtr2?
For example, let num's address 0x7fffaca780b4. Then when I run this code, the output is
10
10
10
0x7fffaca780b4
0x7fffaca780b4
0x7fffaca780b8
Sorry for my bad english
numPtr1 and numPtr2 are two different variables. So where those variables are located will be different, regardless of where they point to.
numptr2 is pointing to numptr1 varible,numptr1 is pointing to num.
So in numptr2 address of numptr1 will be stored & in numptr1 address of num will be stored
both(numptr1,num) addresses are different.
this is the reason that the you get different address.
Why numPtr2's address is not the same with numPtr1, numPtr2?
Each variable has its own address in memory so their content may be same but their address can't be same otherwise it would be impossible to differentiate them.
About [num]
value of [num] = 10
memory location of [num] = 0115FC14
About [numPtr1]
value of [numPtr1] when it dereferenced = 10
address of [numPtr1] is holding = 0115FC14
memory location of [numPtr1] = 0115FC08
About [numPtr2]
value of [numPtr2] when it dereferenced once = 0115FC14(*numPtr2)
value of [numPtr2] when it dereferenced twice = 10(**numPtr2)
address of [numPtr2] holding = 0115FC08(numPtr2) is equals to memory location of [numPtr1] = 0115FC08(&numPtr1)
memory location of [numPtr2] = 0115FBFC
Name
num
numPtr1
numPtr2
Value
10
0115FC14
0115FC08
Memory location
0115FC14
0115FC08
0115FBFC
Here is the code
#include <stdio.h>
int main(void)
{
int a = 5;
int* a_ptr1 = &a;
int** a_ptr2 = &a_ptr1;
puts("***About [a]***");
printf("value of [a] = %d\nmemory location of [a] = %p\n\n", a, &a);
puts("***About [a_ptr1]***");
printf("value of [a_ptr1] when it dereferenced = %d\n", *a_ptr1);
printf("address of [a_ptr1] is holding = %p\n", a_ptr1);
printf("memory location of [a_ptr1] = %p\n\n", &a_ptr1);
puts("***About [a_ptr2]***");
printf("value of [a_ptr2] when it dereferenced once = %p(*a_ptr2)\n", *a_ptr2);
printf("value of [a_ptr2] when it dereferenced twice = %d(**a_ptr2)\n", **a_ptr2);
printf("address of [a_ptr2] holding = %p(a_ptr2) ", a_ptr2);
printf("is equals to memory location of [a_ptr1] = %p(&a_ptr1)\n", &a_ptr1);
printf("memory location of [a_ptr2] = %p\n\n", &a_ptr2);
printf("Name\t\t[a]<---------[a_ptr1]<-------[a_ptr2]\n");
printf("Value\t\t%d %p %p\n", a, a_ptr1, a_ptr2);
printf("Address\t\t%p %p %p\n", &a, &a_ptr1, &a_ptr2);
}

Printing what is stored in pointer prints what is stored in that memory adress

When I try to print this
#include <stdio.h>
int main(){
int x = 3;
int *ptr = &x;
//printf("Address is : %d\n",&ptr);
ptr++;
*ptr = 1;
printf("%d %d",x,ptr);
return 0;
}
The code outputs 3 1, shouldn't it be 3 (then address of ptr?). Then, when I uncomment first printf it prints out:
Address is : 6356744
3 6356752
Does anyone know what is going on?
You have several serious problems in your code.
1) You print a pointer value or an address of a variable using %d but should not. That is undefined behavior so we can't know what will happen. To print a pointer value or an address of a variable use %p and cast to a void pointer like:
printf("Address is : %p\n",(void*)&ptr);
2) You write to memory that is not allocated to your program. These lines:
ptr++;
*ptr = 1;
make you write the value "1" one step past x. So this is also undefined behavior.
Correction the above could give you this program:
#include <stdio.h>
int main(){
int x = 3;
int *ptr = &x;
printf("Address is : %p\n",(void*)&ptr);
ptr++;
// *ptr = 1;
printf("%d %p\n",x,(void*)ptr);
return 0;
}
With the possible output:
Address is : 0x7ffc5b0923c8
3 0x7ffc5b0923c8
but the output may change from run-to-run and system-to-system

Assigning Pointers, Address operators and dereferencing pointers in C

could you explain the following code,
int main() {
int value = 2;
int *ptrWithAmpersand = &value;
int *ptrWithoutAmpersand = value;
//printf("%d", *ptrWithoutAmpersand); 1) Why Runtime error.
printf("Pointer with & --> %d\n", *ptrWithAmpersand);
printf("Pointer withOUT & and * --> %d\n", ptrWithoutAmpersand); //2) Why this works??!!
getch();
}
As commented in the code
Why Runtime Error?
Why this works?
Output is
Pointer with & --> 2
Pointer withOUT & and * --> 2
In the line
int *ptrWithAmpersand = &value;
you are creating a pointer to int and assigning the address of the variable value to it. So far so good.
In the line
int *ptrWithoutAmpersand = value;
you are creating a pointer to int and assigning the contents of the variable value (2) to it. This leads to several problems:
You are attempting to assign a value of type int to a variable of type int *, which are not compatible types; the compiler should at least issue a warning of "incompatible types in assignment" or something like that (turn on all warnings)
On your system, 2 is not a valid object address, hence the runtime error when you try to dereference ptrWithoutAmpersand.
You have several other problems in your code. You should not use the %d conversion specifier to print out pointer values; always use %p for that purpose.
Here's a slight rewrite of your code to makes some things a little clearer:
#include <stdio.h>
int main() {
int value = 2;
int *ptrWithAmpersand = &value;
int *ptrWithoutAmpersand = value; // throws a warning in gcc; you should not do this
printf("value of expression \"value\" = %d\n", value );
printf("value of expression \"&value\" = %p\n", (void *) &value );
printf("value of expression \"ptrWithAmpersand\" = %p\n", (void *) ptrWithAmpersand );
printf("value of expression \"*ptrWithAmpersand\" = %d\n", *ptrWithAmpersand );
printf("value of expression \"ptrWithoutAmpersand\" = %p\n", (void *) ptrWithoutAmpersand );
return 0;
}
And here is the output of the code:
value of expression "value" = 2
value of expression "&value" = 0x7ffecb63cf44
value of expression "ptrWithAmpersand" = 0x7ffecb63cf44
value of expression "*ptrWithAmpersand" = 2
value of expression "ptrWithoutAmpersand" = 0x2
Note how the pointer expression are printed out vs. the integer expressions.
In short:
*ptrWithAmpersand == value == 2 type == int
ptrWithAmpersand == &value type == int *
ptrWithoutAmpersand == value == 2 mismatched types int * and int
In:
int *ptrWithAmpersand = &value;
printf("Pointer with & --> %d\n", *ptrWithAmpersand);
you correctly assign an address to the pointer and in the printf you correctly dereference it to print an int with the %d parameter.
In:
int *ptrWithoutAmpersand = value;
printf("Pointer withOUT & and * --> %d\n", ptrWithoutAmpersand);
You are incorectly assigning an integer value to a pointer, but because in the printf you do not dereference it, it will be printed as an int with the %d parameter. This will only cause a problem (UB) if sizeof(int *) != sizeof(int).
In:
int *ptrWithoutAmpersand = value;
printf("%d", *ptrWithoutAmpersand);
you get a runtime error because you are dereferencing a pointer that points to memory address 2, which is not yours and so the system aborts your program.

Why can't I swap memory address of two variables using a function? C

static void swapAddr(int *numOne, int *numTwo)
{
int *tmp;
tmp = numOne;
numOne = numTwo;
numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
printf("a is: %d\n", a);
printf("Address of a: %p\n", &a);
printf("b is: %d\n", b);
printf("Address of b: %p\n", &b);
swapAddr(&a, &b);
printf("\n");
printf("a is: %d\n", a);
printf("Address of a: %p\n", &a);
printf("b is: %d\n", b);
printf("Address of b: %p\n", &b);
return 0;
}
When I compile and run this piece of code, the output is
a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94
a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94
Clearly the result is not what I intended, since the address does not seem to have been swapped at all.
You generally can't change the address of a variable.
Your 'swapAddr' function changes its parameter values, but these are local to the function - you're not changing anything outside the function. Perhaps the best way of understanding it is that a function parameter always receives a copy of the value that was passed to the function. In this case, you get a copy of the address of a and a copy of the address of b. You can and do change the values of the variables holding those copies (numOne and numTwo), and seeing as they are pointers you could (but don't) change the values that they point at (the values of variables a and b) - but you can't change the addresses of the original variables.
To break it down:
static void swapAddr(int *numOne, int *numTwo)
{
int *tmp;
tmp = numOne;
At this point, tmp and numOne both point to the value of the a variable...
numOne = numTwo;
Now, numOne points instead to the value of the b variable...
numTwo = tmp;
}
And finally, numTwo now points to the value of the a variable. The function returns and numOne and numTwo no longer exist after that point. The addresses of the variables a and b did not change at any stage.
You could however write a function which exchanges the addresses in two pointer variables:
static void swapAddr(int **ptrOne, int **ptrTwo)
{
int *tmp;
tmp = *ptrOne;
*ptrOne = *ptrTwo;
*ptrTwo = tmp;
}
This would allow you to pass the address of two pointer variables, and on return the pointers would be swapped - each one pointing at what the other did previously. But again, this would not change the address of any variable that those pointers happened to point to.
The pointers are passed to the function by value, so changing what they point to isn't going to change the value of the passed parameters in the calling function.
When the function is called, a copy of each pointer is made and saved to the stack. Then the function reads each pointer value off the stack and manipulates them. It never changes the value of the original pointer that was copied onto the stack.
Remember that in C values are passed by value to functions, meaning that the values are copied. When you modify an argument in a function you only modify the local copy inside the function, not the original value that was passed to the function. This goes for pointers as well.
To solve your problem you must pass the arguments by reference, but unfortunately C doesn't have that, it only have pass by value. However, pass by reference can be emulated by passing pointers to the data, just like you do in the function. You must however dereference the pointer to get the values from where the pointers point to, and use those values to do the actual swapping:
int temp = *numOne; // Note: temp is a value not a pointer
*numOne = *numTwo;
*numTwo = temp;
static void swapAddr(int *numOne, int *numTwo)
In this function you are passing 2 pointers by value. This allows you to modify the int pointed to by the pointers but not the pointers themselves.
Use this function definition instead that passes pointers to pointers and allows modifying the pointers themselves
static void swapAddr(int **numOne, int **numTwo) {
int *tmp = *numOne;
numOne = *numTwo;
numTwo = tmp;
}
You could use it like this for example:
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
*a = 15;
*b = 10;
swapAddr(&a, &b);
You canlt change the addresses. The adderss of a is the address of a and that will remain the same until the end of days.
You can do:
static void swapAddr(int **numOne, int **numTwo)
{
int *tmp;
tmp = *numOne;
*numOne = *numTwo;
*numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
int *pa= &a;
int *pb= &b;
swapAddr(&pa, &pb);
}
What you want to achieve is something like
int *c = &a;
&a = &b;
&b = &a;
This is not possible (you can check: it will not compile). A variable that is created is placed at one place in memory and stays there. So when you create a variable a it will stay variable a and it will not be able to change its identity to that of another variable b.
What you can do is use two pointers int *p1, *p2 to int. These pointers can change their value and point to other objects during lifetime:
p1 = a;
p2 = b;
p1 = b;
p2 = a;
a and b will stay the same, but p1 and p2 can point to different objects over time.
So a thing that would be possible:
static void swapaddr(int **pp1, int **pp2)
{
int *pp;
pp = *pp1;
*pp1 = *pp2;
*pp2 = pp;
}
int main(void)
{
int a = 15, b = 10;
int *pA = &a, *pB = &b;
swapAddr(&pA, &pB);
}
In this example a and b would keep their identity and address, but pA and pB would change their value and pA would point to b and pB would point to pA.
You cannot change the addresses of the variables.however you can change values of pointers,which store addresses as their value,here is an example :
#include <stdio.h>
void swapAddr(int **numOne, int **numTwo)
{
int *tmp;
tmp = *numOne;
*numOne = *numTwo;
*numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
int *p_a = &a;
int *p_b = &b;
printf("Address of a: %p\n", p_a);
printf("Address of b: %p\n", p_b);
swapAddr(&p_a,&p_b);
printf("\n");
printf("p_a : %p\n",p_a);
printf("p_b : %p\n",p_b);
return 0;
}

Resources