Below is the test code:
#include <stdio.h>
int funtion(int *ptr)
{
int temp;
temp = *ptr;
printf("ptr = %p %p %p %d\n", ptr, &ptr, &ptr[0], *ptr);
printf("*ptr = %d\n", *ptr);
return temp;
}
int main()
{
int i = 10;
int *tp = &i;
printf("tp = %p %p %p %d\n", tp, &tp, &tp[0], *tp);
(void)funtion(tp);
return 0;
}
answer:
tp = 0x7ffc1117392c 0x7ffc11173930 0x7ffc1117392c 10
ptr= 0x7ffc1117392c 0x7ffc111738f8 0x7ffc1117392c 10
*ptr =10
**question:
what are the difference between tp &tp &tp[0]
Which passing parameter we should use.
is this difference only for passing parameter?**
You are passing an int pointer to function. This is passed by value. Of course, the value they point to is the same.
int funtion(int *ptr)
{
int temp = *ptr;
printf("ptr = %p %p %p %d\n", ptr, &ptr, &ptr[0], *ptr);
printf("*ptr = %d\n", *ptr);
return temp;
}
temp is initialized with the value pointed to by ptr.
The first thing you print is ptr: the memory address you passed to function by value.
The second thing you print is &ptr. This is the address of that function argument. While this may be the same between function calls due to implementation-specific handling of the stack, it may also be different.
The third thing you print is &ptr[0]. This is the address is ptr[0], which is equivalent to writing *(ptr + 0) or just *ptr. Getting the address of this in turn is equivalent to just writing ptr.
The fourth thing you print is *ptr. Again, as with initializing temp this is just the int value that ptr points to.
1. what are the difference between tp &tp &tp[0]
Its their type.
The type of tp is int *.
The type of &tp is int **.
The type of &tp[0] is int * because &tp[0] is equivalent to tp1) :
&tp[0] -> &(tp[0]) -> &(*(tp) + (0)) -> &(*tp) -> tp
Note : You do not need to use [0] with pointer to access the value of a scalar type, which the pointer is pointing at.
2. Which passing parameter we should use.
Its not clear, what exactly you want to ask.
You are passing value of tp to function() function which is nothing but &i. The ptr parameter of function() function will hold the &i when it is called. If you want to make changes to the value of i within the function() function then you can do it because ptr hold address of i and *ptr will give value at that address which is nothing but the value of variable i. If you just want to access the value of i, you can simply pass the value of variable i.
3. is this difference only for passing parameter?
Which difference? I believe, you mean - why there is difference in &tp and &ptr?
ptr is local variable of function() function and tp is local variable of main() function. Though, they both hold the address of variable i their own addresses are different because they are different variables.
1). C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..
Related
I noticed that my pointer address is different when it is passed to a function. U am not sure to access the value that exists inside the function? Please don't suggest returning the pointer value from the function. I strictly want to use void function.
output:
&nPtr = 6422300
&Ptr = 6422272
&nPtr = 6422300
See the below code:
#include<stdio.h>
void myFunc(int *Ptr){
printf("&Ptr = %d\n", &Ptr);
};
void main(){
int *nPtr;
printf("&nPtr = %d\n", &nPtr);
myFunc(nPtr);
printf("&nPtr = %d\n", &nPtr);
}
Let me be more clear. Here is the code that I am trying to fix. All what I want is to make the two pointers point to the same address. I want to use the best coding practice.
#include<stdlib.h>
#include<stdio.h>
void myFunc(int *Ptr){
Ptr = malloc(10*sizeof(int));
printf("*Ptr = %d\n", *Ptr);
};
void main(){
int *nPtr;
printf("*nPtr = %d\n", *nPtr);
myFunc(nPtr);
printf("*nPtr = %d\n", *nPtr);
}
In main(), you're getting the address of nPtr in main()'s stack frame; in myFunc(), you're getting the address of the copy of nPtr that is being passed by value to myFunc() as Ptr (so you're actually getting the address of Ptr, which is distinct) and exists on myFunc()'s stack frame.
nPtr and Ptr are separate variables in separate functions, and as such each must necessarily have a different address, i.e. &nPtr == &Ptr will always be false.
But you asked about nPtr == Ptr, i.e. can they contain the same value, and as pointers they can both contain the same pointer value. For example:
#include<stdio.h>
void myFunc(int *Ptr){
printf("Ptr = %p\n", (void *)Ptr);
};
int main(){
int x;
int *nPtr = &x;
printf("nPtr = %p\n", (void *)nPtr);
myFunc(nPtr);
printf("nPtr = %p\n", (void *)nPtr);
}
Output:
nPtr = 0x7ffe9a615104
Ptr = 0x7ffe9a615104
nPtr = 0x7ffe9a615104
For this function
void myFunc(int *Ptr){
printf("&Ptr = %d\n", &Ptr);
};
when you call it, although you are passing a pointer (which is for pointing to an integer) to this function , the system is creating a copy of the pointer and of course they will be at different memory address.
Hence when you return back to the main and retrieve your original pointer address, it will be displaying back the original address
I am doing a homework of C programming.
#include <stdio.h>
typedef struct JustArray {
char *x;
} JustArray;
int main()
{
JustArray Items[12];
char *d = "Test";
Items[0].x = (char *) &d;
printf("Pointer: %p\n", &d);
printf("Address: %u\n",&d);
printf("Value: %s\n", d);
/*------------------------------------*/
//Knowing address of d from above, print value stored in it using Items[0].x. Cannot use &d, *d, or d.
char *ptr;
ptr = Items[0].x;
printf("%p\n", Items[0].x);
printf("%p\n", &ptr);
printf("%s\n", ptr);
return 0;
}
The output of ptr needs to be "Test" as well but it is showing me weird characters. The assignment is to have find a way to use the address info in Items[0].x and print its value "Test" in console. I could not find a way to do it...
Remember that the value of a pointer is an address. The content of a pointer (i.e. its dereference, the value pointed, addressed by it) is a value (with the type being pointed) which is in another place. So a int* has as value an address of another variable (of type int) which is stored in another address. Note that each primitive variable in C is the name of a data stored in some address.
int p = 1;
p above is a var of type int. It has 1 as value, which is directly given by p (so p == 1). p has an address (say 0x11111) that can be accessed with &p (so &p == 0x11111). Thus, p is the name of a variable whose value is an int (1) and whose address is 0x11111 (given by &p). This means that the value 1 (which is an int) is stored in the address 0x11111.
int* q = 0x22222;
q above is a var of type int* (pointer to int, meaning "an address to a var of type int"). q has an address as value (in this case is 0x22222), which is directly given by q (so q == 0x22222). but q also has an address (say 0x33333), which can be accessed with &q (so &q == 0x33333). Thus, q is the name of a variable whose value is an address to int (0x22222, given by q) and whose address is 0x33333 (given by &q). Basically, the value 0x22222 (which is an address) is stored in the address 0x33333.
You can use the prefix operator * over q to dereference it, i.e. access its content, which is the value stored in the address 0x22222, which is the value of q. So basically we have: q==0x22222, &q==0x33333, and *q==[whatever is the value stored in the adress 0x22222]. Now consider this:
int* r = &p;
Remember that p has value 1 (an int given by p itself) and address 0x11111 (given by &p). Now I declared a pointer to int called r and initialized it with the address of p (0x11111). Thus, r is a pointer whose value is an adress (0x11111), but it also has an address (say 0x44444).
The operator * prefixing a pointer lets us access the value of the address that is its value. So *r will give us 1 because 1 is the value stored in the address 0x11111, which is the value of r and the address of p at the same time. So r==&p (0x11111==0x11111) and *r==p (1==1).
Now lets go back to your code. When you declare a char* you already have a pointer, so the printing of it will be an address if you set %p as the desired format or a string if you set %s as the desired format. (The %s makes the function printf iterate throughout the contents whose start address is the value of the given pointer (and it stops when it reaches a '\0'). I fixed your code (and modified it a little bit for the sake of readability). The problem was that you were sending the addresses of the pointers instead of the pointers themselves to the function printf.
#include <stdio.h>
typedef struct justArray
{
char* x;
}
JustArray;
int main()
{
//d is a pointer whose content is an address, not a char 'T'
char* d = "Test";
printf("Pointer: %p\n", d); //print the address (no need for &)
printf("Address: %lu\n", (long unsigned) d); //print the address again as long unsigned)
printf("Value: %s\n", d); //print a string because of the %s
JustArray Items[12];
Items[0].x = d;
printf("%p\n", Items[0].x); //Items[0].x == d, so it prints the same address
char* ptr = Items[0].x;
printf("%p\n", ptr); //ptr == Items[0].x, so it prints again the same address
printf("%s\n", ptr); //prints the string now because of the %s
return 0;
}
The output of this program will be:
Pointer: 0x400734
Address: 4196148
Value: Test
0x400734
0x400734
Test
The key here is to notice what this line does:
Items[0].x = (char *) &d;
Observe first that d is a char * (i.e. a null-terminated string in this case), thus &d (taking a reference to it) must yield a value of type char * * (i.e. a pointer to a pointer to a char, or a pointer to a string). The cast to char * has to be done for the C type checker to accept the code. [Note that this is considered very bad practice, since you are forcing a value of one type into a value of another type that makes no sense. It's just an exercise though, and it's precisely this "bad practice" that makes it a bit of a challenge, so let's ignore that for now.]
Now, to get back d again, given just Items[0].x, we need to sort of "invert" the operations of the above line of code. We must first convert Items[0].x to its meaningful type, char * *, then dereference the result once to get a value of type char * (i.e. a null-terminated string).
char *d_again = *((char * *) Items[0].x);
printf("%s\n", d_again);
And viola!
#include<stdio.h>
int func(int*);
int main(void)
{
int a = 3;
int *p = NULL;
p = &a;
printf("p = %p\n", p);
func(p);
printf("p inc: %p\n", p);
return 0;
}
int func(int *p)
{
p++;
return 0;
}
Output: p=0x7fff6f87e89c
p inc:0x7fff6f87e89c
Pointer p is passed to function func and pointer p is incremented in func, but in main function its address is still the same!! Passing pointer to function is'nt passing by reference?
Pointers are passed by value.
If you want to pass a pointer by reference, you just pass a pointer of a pointer!
Like so:
#include<stdio.h>
int func(int**);
int main(void)
{
int a = 3;
int *p = NULL;
p = &a;
printf("p = %p\n", p);
func(&p);
printf("p inc: %p\n", p);
return 0;
}
int func(int **p)
{
(*p)++;
return 0;
}
There's no passing by reference in C. When you pass a pointer to a function, you are passing a memory address by value.
When, inside the function, you do this:
int func(int *p)
{
p++;
return 0;
}
...you are only incrementing the memory address indicated by the parameter p by sizeof *p bytes.
In order to "simulate" passage by reference in C, you need to explicitly dereference the pointer to access the actual object. If p is a properly assigned and valid pointer, then *p is the object it points to. If a non-pointer expression were this:
a = a + 1;
...then with p == &a it would become this:
*p = *p + 1;
...or simply (*p)++. Notice that the parenthesis are necessary because, otherwise, C will read this as *(p++). You can also get used to writing ++*p instead.
You increment the pointer, not the value.
Try like this
(*p)++;
And
printf("p inc: %d\n", *p);
You need to understand pointers. A pointer is simply a variable that stores the memory address where the data actually is. You can access the data by using the dereference operator *, so if you want to change the data, you simply dereference the pointer, and then modify the data.
Likewise, for printing you want to see the value of the data.
In your code, you only modify the pointer. In c you always pass by value, a copy of the pointer itself is created inside the func() function, initially it holds the same address as your original pointer, but since it's a copy, increment it will only affect the address in the local copy.
Further more, since it's pointing to a variable on the stack. The increment operation on it will result in a pointer that you can't dereference because it would be undefined behavior.
If you want to increment the address of the pointer, you need to pass a pointer to the pointer, like this
void func(int **p)
{
(*p)++;
}
and in main
func(&p);
note that the body of func() is the same, because you once again need to get access to the memory pointed to by p in order to modify it.
In the following code p is pointer to an int. It is quite clear that p points to the address of i. Through my research i know &p points to the address of pointer p. But i don't get why would you need separate address for that. And also when would you use &p.
int main() {
int i = 3, *p = &i;
printf("%p",&p);
printf("%p",p);
return 0;
}
If p is pointer to int then
int **q = &p;
When you want to use pointer to pointer, then use the address of a single pointer to assign it to pointer to pointer.
Just to make a point that pointer is also a data-type and it stored in the memory location and it holds a valid memory location as its value. The address in which this valid memory location is stored is given by &p
Your printf() also needs to be fixed. %p expects void *
printf("%p",(void *)p);
But i don't get why would you need separate address for that
You don't, but there exists the address of operator so you can take the address of a pointer, which is what
printf("%p\n", &p);
is printing.
And also when would you use &p
There are cases where this might be useful, consider for example that you need to pass a pointer to a function which could be reassigned into the function, you can do something like this
int allocateIntegerArray(int **pointerToPointer, size_t someSize)
{
if (pointerToPointer == NULL)
return 0;
*pointerToPointer = malloc(someSize * sizeof(int));
return (*pointerToPointer != NULL);
}
then you could use this funciton the following way
int *pointer;
if (allocateIntergerArray(&pointer, 10) == 0)
{
fprintf(stderr, "Error, cannot allocate integer array\n");
/* do some extra cleanup or recover from this error, or exit() */
exit(0);
}
The pointers themselves are also variables and as such they need to be sotred somewhere, so the address of a pointer tells you where is the pointer stored, it's value tells you where it is pointing to.
By knowing where it is stored you can do things like the one explained above.
A trivial example:
int nochange(int *c, int *val)
{
c = val; // Changes local pointer c to point to val
// Note that C passes copies of the arguments, not actual references.
}
int do_change(int **c, int *val)
{
*c = val; // Accesses the real pointer c at its real location and makes
// that one point to val
// Even though c is a pointer-to-pointer copy, its value is
// copied too, and the value is the address of the real c
}
int main()
{
int a = 1;
int b = 2;
int *c = &a; // A pointer is also a datatype that resides in memory
printf("%d\n", *c); // Will print 1
nochange(c, &b);
printf("%d\n", *c); // Will print 1
do_change(&c, &b);
printf("%d\n", *c); // Will print 2 because c now points to b
}
I have a similar answer with a bit more detail here about pointer vs pointer-to-pointer: pointer of a pointer in linked list append
I am trying to initialize the integer pointer "p" inside the "init_pointer" function. After the function returns I am printing the pointer and the dereferenced value twice. The first dereference prints the expected value 100, but the second dereference prints random values.
#include<stdio.h>
void init_pointer(int d, int **c){
(*c) = &d;
}
int main(){
int x = 100;
int *p;
init_pointer(x,&p);
printf("pointer = %p, value = %d\n",p,*p);
printf("pointer = %p, value = %d\n",p,*p);
return 0;
}
Output:
pointer = 0x7fffb4d4b9ac, value = 100
pointer = 0x7fffb4d4b9ac, value = 32567
The function has copied the value to a new local variable in init_pointer(int d, int **c)
d is local to init_pointer which was passed by main from x. Both x and d are separate variables whose addresses are different. Accessing the address of d outside init_pointer will lead to Undefined Behavior.
It would not make sense to call the function like this but this will work:
void init_pointer(int *d, int **c)
{
(*c) = d;
}
int main()
{
int x = 100;
int *p;
init_pointer(&x,&p);
printf("pointer = %p, value = %d\n",p,*p);
printf("pointer = %p, value = %d\n",p,*p);
return 0;
}
Output:
pointer = 0xbfde132c, value = 100
pointer = 0xbfde132c, value = 100
void init_pointer(int d, int **c){
(*c) = &d;
}
Here *c points to a local copy inside init_pointer(). Once init_pointer() returns, the address becomes invalid, and p in main() points to a freed address.
In init_pointer you assign the address of the parameter d to *c. The address of the parameter is a stack address.
In the first call to printf, the stack (although deallocated) is still intact, so p points to the discarded parameter d on the stack, which still has a value of 100, and *p is pushed first onto the stack.
In the second call to printf, the first call has overwritten the stack. Although the pointer still points to the same address, its value there has been overwritten by the push of p. Hence p (an address) is printed.
Notes: with "the stack (although deallocated)" I mean the stack of and below sp (intel; growing downward). Also, the stack can have been overwritten at any time, e.g. when interrupts occur.