In the code below I set the variable var to 20, then the pointer ptr to the address of var. Then the pointer ptrptr to hold the memory address of the pointer ptr.
#include <stdio.h>
void pointers()
{
int var = 20;
int* ptr;
ptr = &var;
int *ptrptr = ptr;
printf("Value at ptrptr[0] = %d \n", ptrptr[0]);
}
// Driver program
int main()
{
pointers();
return 0;
}
Output:
Value at ptrptr[0] = 20
Why does ptrptr[0] return the value stored by val, and not the memory address of the pointer ptr.
I thought that the indexing operator [] returns the value stored by that value.
Here is an example which will, I hope, make it more clear what's going on.
#include <stdio.h>
int main()
{
int var = 20;
int *ptr = &var;
int *ptr2 = ptr;
printf("the value of the variable var is %d\n", var);
printf("the address of the variable var is %p\n\n", &var);
printf("the value of the pointer ptr is %p\n", ptr);
printf("the value pointed to by ptr is %d\n", *ptr);
printf("or, stated another way, it's %d\n\n", ptr[0]);
printf("the value of the pointer ptr2 is %p\n", ptr2);
printf("the value pointed to by ptr2 is %d\n", *ptr2);
}
On my machine this prints:
the value of the variable var is 20
the address of the variable var is 0x7ffeed56992c
the value of the pointer ptr is 0x7ffeed56992c
the value pointed to by ptr is 20
or, stated another way, it's 20
the value of the pointer ptr2 is 0x7ffeed56992c
the value pointed to by ptr2 is 20
Since ptr and ptr2 have the same type (int *), and since they hold the same pointer value (since we said ptr2 = ptr), they behave the same.
And because of the "correspondence between arrays and pointers" in C, *ptr is identical to ptr[0]. Both expressions yield the value pointed to by ptr.
If your intention with ptrptr was to have it be a pointer to a pointer, here's an illustration of that wrinkle. Since ptrptr is a two-level pointer, its pointed-to value is actually another pointer, so you have to be really careful thinking about it.
int **ptrptr = &ptr;
printf("the value of the pointer ptrptr is %p\n", ptrptr);
printf("the value pointed to by ptrptr is %p\n", *ptrptr);
printf("and the value pointed to by that pointer is %d\n", **ptrptr);
This additionally prints:
the value of the pointer ptrptr is 0x7ffeed569920
the value pointed to by ptrptr is 0x7ffeed56992c
and the value pointed to by that pointer is 20
By definition *(ptr + n) === ptr[n]
Why does ptrptr[0] return the value stored by val, and not the memory
address of the pointer ptr.
I thought that the indexing operator [] returns the value stored by
that value.
no ptr[x] dereferences the pointer.
int x = 5;
int *ptr = &x;
int *ptrptr = ptr; //this assigns reference stored in ptr to ptrptr. Now they store the same reference.
printf("Dereferencing pointer - %d\n", ptr[0]);
printf("Reference stored in the pointer - %p\n", (void *)ptr);
printf("Reference of the pointer (its address) - %p\n", (void *)&ptr);
Judging from the name of your second pointer you probably wanted pointer to pointer
int x = 5;
int *ptr = &x;
int **ptrptr = &ptr; //poiter to pointer
printf("Dereferencing pointer to pointer - reference of x %p\n", (void *)ptrptr[0]);
printf("Reference stored in the pointer to pointer - reference of ptr%p\n", (void *)ptrptr);
printf("Reference of the pointer (its address) - %p\n", (void *)&ptrptr);
This
ptrptr[0]
is the same as (because ptrptr and ptr are same type and have same value):
ptr[0]
is the same as (because a[b] == *(a+b)):
*ptr
is the same as var, because ptr points to var, and *ptr is dereferencing the pointer.
The value of var is 20.
ptrptr has the same type as ptr, a pointer to an int. So when you do int *ptrptr = ptr;, now ptrptr and ptr point to the same address (that's why it compiles as well). Also ptrptr[0] is the same as to *ptrptr
You have to define ptrptr to be a pointer to a pointer of an int:
int **ptrptr = &ptr;
printf("Value at ptrptr[0] = %d \n", *ptrptr[0]);
if you wanted ptrptr to point to ptr
Link to Compiler Explorer.
You never set ptrptr to hold the memory address of ptr but to the value of ptr itself. Below is an image for illustration. First ptr is assigned the address of var and then ptrptr is assigned the value of ptr, so it also points to var.
To make ptrptr point to ptr you need to declare it as
int **ptrptr = &ptr;
Related
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Passing pointer to function value not changing [duplicate]
(4 answers)
Closed 1 year ago.
I don't understand the behavior of this program.
By my understanding, pointer in main() should have the original address of the local variable that is, now, destroyed. Because pointer was assigned the valid address at that point.
It should just keep that address. Why is it losing that?
Here's the program
#include <stdio.h>
void fun(int* ptr)
{
int a = 5;
ptr = &a;
printf("address: %p, value: %d\n", &a, a);
// address: 0x7fff1aa00374, value: 5
printf("address: %p, value: %d\n", ptr, *ptr);
// address: 0x7fff1aa00374, value: 5
}
int main(void)
{
int* ptr = NULL;
fun(ptr);
printf("address: %p\n", ptr);
// address: (nil)
printf("address: %p\tvalue: %d\n", ptr, *ptr);
// Segmentation fault (core dumped)
return 0;
}
GCC Version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Here is a modified example:
#include <stdio.h>
void fun(int p)
{
p = 5;
printf("value: %d\n", p);
}
int main(void)
{
int p = 0;
fun(p);
printf("value: %d\n", p);
return 0;
}
If you understand why this modified example prints 5 then 0, then you also understand why your pointer version doesn't work either. Because pointers too are passed by value.
If you don't understand why this prints 5 then 0, then you need to read a beginner-level C book, functions chapter.
For better understanding of what's happening here, renaming the ptr parameter of fun() function to fun_ptr
void fun(int* fun_ptr)
^^^^^^^
When you call fun() function
int* ptr = NULL;
fun(ptr);
the value of argument ptr will be assigned to fun() function parameter fun_ptr. Its similar to this
fun_ptr = ptr;
ptr is NULL, so the fun_ptr will be assigned NULL. Whatever changes you do in fun_ptr inside fun() function will stay within fun() function block because the scope of identifier within the list of parameter declarations in a function definition has block scope which terminate when function returns.
If you want to make changes to a pointer variable in another function, you have to pass the address of that pointer variable to the calling function. In context of your program, it should be
void fun(int** ptr) {
int a = 5;
*ptr = &a;
// *ptr will be the pointer passed as argument i.e. assign anything
// to *ptr means you are making changes to pointer passed as argument
.....
.....
}
int main(void)
{
int* ptr = NULL;
fun(&ptr);
.....
.....
return 0;
}
Even after making these changes your program will have Undefined Behaviour because it is accessing address of local variable outside of its scope. Variable a is a local(automatic) non-static variable and its lifetime is limited to its scope i.e. the block in which it has been declared. Any attempt to access it outside of its lifetime lead to undefined behaviour.
To resolve this, allocate memory to pointer ptr and assign the value of a to it. Or, you can declare a as static variable. The lifetime of a static variable is entire run of the program. You can do:
#include <stdio.h>
#include <stdlib.h>
void fun1 (int** ptr) {
static int a = 5;
*ptr = &a;
printf("fun1(): address: %p, value: %d\n", (void *)&a, a);
printf("fun1(): address: %p, value: %d\n", (void *)*ptr, **ptr);
}
void fun2 (int** ptr) {
int a = 5;
*ptr = malloc (sizeof (int));
if (*ptr == NULL) {
fprintf (stderr, "Failed to allocate memory\n");
exit (EXIT_FAILURE);
}
**ptr = a;
printf("fun2(): address: %p, value: %d\n", (void *)&a, a);
printf("fun2(): address: %p, value: %d\n", (void *)*ptr, **ptr);
}
int main (void) {
int* ptr1 = NULL;
int* ptr2 = NULL;
fun1(&ptr1);
printf("main(): address: %p\n", (void *)ptr1);
printf("main(): address: %p, value: %d\n", (void *)ptr1, *ptr1);
fun2(&ptr2);
printf("main(): address: %p\n", (void *)ptr2);
printf("main(): address: %p, value: %d\n", (void *)ptr2, *ptr2);
// Once done with dynamic allocated memory, release it
free(ptr2);
return 0;
}
This is because you are passing by value, just like passing an integer, char, etc. You cannot change a parameter passed by value. In this case, the value is the address. To actually change the address of ptr would require passing a passing a double pointer (int **ptr), but that would require more changes to your code.
#include <stdio.h>
struct Analysis {
int lnlen;
int arr[2];
char* name;
};
int main()
{
struct Analysis ana_space[2];
char *ptr = (void*) &ana_space;
ana_space[0].lnlen = 0;
ana_space[0].arr[0] = 1;
ana_space[0].arr[1] = 2;
ana_space[0].name = "Peter";
printf("\n%d\n", *ptr); // print 0;
*ptr = 10; // how to use memcpy here;
printf("\n%d\n", *ptr); // print 10;
ptr = ptr + sizeof(int); // advance pointer by int;
printf("\n%d\n", *ptr); // print 1;
ptr = ptr + 2*sizeof(int); // advance pointer by 2 ints;
printf("\n%s\n", *ptr); // print "Peter"; --------------not work
//*ptr = "Jim"; // how to assign new name "Jim" into that memory;
return 0;
}
Output:
0
10
1
(null)
I want to use char * as pointer to go through memory address to get some data and also store value into memory.
For int and int array, it works fine, but not for the string.
How to print the string and store new string value into memory?
Your approach is not portable. It will be better to use offsetof to make sure that you can reliably point to the addresses of the members of a struct.
int main()
{
struct Analysis ana_space[2];
char *ptr = (void*) &ana_space;
size_t offset1 = offsetof(struct Analysis, arr);
size_t offset2 = offsetof(struct Analysis, name);
ana_space[0].lnlen = 0;
ana_space[0].arr[0] = 1;
ana_space[0].arr[1] = 2;
ana_space[0].name = "Peter";
// advance pointer to point to arr.
ptr = ptr + offset1;
// advance pointer to point to name
ptr = ptr + (offset2-offset1);
// Cast the pointer appropriately before dereferencing.
printf("\n%s\n", *(char**)ptr);
// how to assign new name "Jim" into that memory;
*(char**)ptr = "Jim";
printf("\n%s\n", *(char**)ptr);
return 0;
}
Your use of:
printf("\n%d\n", *ptr); // print 0;
*ptr = 10; // how to use memcpy here;
printf("\n%d\n", *ptr); // print 10;
and the expected output is flawed. It works only with little endian systems. I suggest using:
printf("\n%d\n", *(int*)ptr);
*(int*)ptr = 10;
printf("\n%d\n", *(int*)ptr);
The code you presented could cause undefined behavior due to padding and representations of types, which are implementation-defined.
After you increment the pointer ptr here:
ptr = ptr + 2*sizeof(int);
the pointer ptr points to the member name of the struct Analysis. If you dereference the pointer ptr, you get the type char and thus a single byte. This byte does not represent a pointer to the string.
The pointer ptr will have to be cast to the type pointer to a pointer to char, and then dereferenced so the correct and full value of the member name will be obtained.
That resulting value is a pointer to the string "Peter".
ANSI C has a macro called offsetof() found in stddef.h that gives a more sure way of calculating the pointer offset of a member within a struct. Here, we can get the the address of the name member in ana_space[0] directly.
ptr = (char*) &ana_space + offsetof(struct Analysis, name);
This takes out any guess work on padding.
This pointer then has to be properly cast to print the contents of name:
printf("%s\n", *(char**) ptr);
I have a below code in C:
#include <stdio.h>
#include <stdlib.h>
int main()
{
typedef struct sample {
int num;
} abc;
typedef struct exmp{
abc *n1;
} ccc;
abc *foo;
foo = (abc*)malloc(sizeof(foo));
ccc tmp;
tmp.n1 = foo;
ccc stack[10];
stack[0] = tmp;
printf("address of tmp is %p\n",&tmp);
// need to print address contained in stack[0]
return 0;
}
In the above code I want to check if the address at stack[0] is same as address of tmp. How do I print address at stack[0] as I printed out tmp's address?
It's very simple, just do this
printf("address of tmp is %p and address of stack[0] %p\n",
(void *)&tmp, (void *)&stack[0]);
and actually this will work
printf("address of tmp is %p and address of stack[0] %p\n",
(void *)&tmp, (void *)stack);
Also, Do not cast malloc(), and always check that the returned value is not NULL, i.e. that it's a valid pointer.
I have two pointers. A char pointer with the string "test", and a void pointer.
I'm trying to have pointer point to the address of string.
Here's my code:
#include <stdio.h>
int main(){
void *pointer = NULL;
char *string = "test";
*(char*)pointer = &string;
printf("The string address: %p\n", string);
printf("The string: %s\n", string);
printf("The pointer address: %p\n", pointer);
printf("The pointer points to: %p", *(char*)pointer);
return 0;
}
When I set pointer to be equal to the address of string on line 6 I get makes integer from pointer without a cast. How can I do this?
Edit:
I was printing the wrong addresses. I meant for the printf lines to look like this:
#include <stdio.h>
int main(){
void *pointer = NULL;
char *string = "test";
pointer = &string;
printf("The string address: %p\n", &string);
printf("The string: %s\n", string);
printf("The pointer address: %p\n", &pointer);
printf("The pointer points to: %p", pointer);
return 0;
}
It now properly prints out this:
The string address: 0028FF18 The string: test The pointer address:
0028FF1C The pointer points to: 0028FF18
So string and pointer are separate pointers and pointer points to string.
Why not simply do
#include <stdio.h>
int main(){
void *pointer = NULL;
char *string = "test";
pointer = &string; // point to the address of string
printf("The string address: %p\n", string);
printf("The string: %s\n", string);
printf("The pointer address: %p\n", pointer);
printf("The pointer points to: %p\n", (char*)(*(char**)(pointer)));
return 0;
}
If you want to point pointer at the string addressed by string,
pointer = string;
works.
If you want to point pointer at string,
pointer = &string;
is sufficient.
What you actually are doing is casting pointer to char*, and assigning through it, which is undefined behavior as pointer is NULL.
Actually, conversion from &string to char probably does not work either.
void *pointer = NULL;
pointer here is a pointer of type void. You need to first make sure that this pointer points to some valid memory location before dereferencing it.
Like
pointer = string;
PS: Here string is a string literal so it is read-only if you try to write to this memory location you might get segmentation fault.
If you want to have a pointer that points to the char pointer string, then you should do this:
pointer = &string
If you want to have a pointer that points to the string "test", then you should do this:
pointer = string
This question already has answers here:
C Programming: malloc() inside another function
(9 answers)
Closed 5 years ago.
I would like to know the technical reason(in terms of memory) why this piece of code will not work:
#include <stdio.h>
#include <stdlib.h>
int* fun(int*);
int main()
{
int a=5;
int* ptr;
// ptr=(int*)malloc(sizeof(int));
fun(ptr);
a=*ptr;
printf("\n the val of a is:%d",a);
return 0;
}
void fun(int* ptr)
{
ptr = (int*)malloc(sizeof(int));
*ptr = 115;
}
Why will this not work? I thought that the heap(more importantly the addresses) is common to all the function's variables in the stack .
Also, why would this work.
If i comment the memory allocation inside the function fun and uncomment the one in main . It works fine.
In C, everything is passed by value.
What you are passing to fun() is a copy of the pointer you have in main().
That means the copy of ptr is aimed at the allocated memory, and that memory set to 115.
The ptr in main() still points at an undefined location because it has never been assigned.
Try passing a pointer to the pointer, so that within fun() you have access to the pointer itself:
#include <stdio.h>
#include <stdlib.h>
int* fun(int**); // <<-- CHANGE
int main()
{
int a=5;
int* ptr;
// ptr=(int*)malloc(sizeof(int));
fun(&ptr); // <<-- CHANGE
a=*ptr;
printf("\n the val of a is:%d",a);
return 0;
}
int* fun(int** another_ptr) // <<-- CHANGE
{
*another_ptr = (int*)malloc(sizeof(int)); // <<-- CHANGE
**another_ptr = 115; // <<-- CHANGE
return *another_ptr;
}
The other option would be to make fun() actually return the updated pointer (as advertised), and assign this to ptr:
#include <stdio.h>
#include <stdlib.h>
int* fun(int*);
int main()
{
int a=5;
int* ptr;
// ptr=(int*)malloc(sizeof(int));
ptr = fun(ptr); // <<-- CHANGE
a=*ptr;
printf("\n the val of a is:%d",a);
return 0;
}
int* fun(int* another_ptr)
{
another_ptr = (int*)malloc(sizeof(int));
*another_ptr = 115;
return another_ptr; // <<-- CHANGE
}
Edit: I renamed the variable in fun() to make it clear that it is different from the one you use in main(). Same name doesn't mean anything here.
The fun() function parameter is a copy of the variable you passed into fun(). So when you do:
ptr = (int*)malloc(sizeof(int));
*ptr = 115;
you only change that copy. You should change the function signature:
int* fun(int** ptr)
{
*ptr = (int*)malloc(sizeof(int));
**ptr = 115;
}
and change how you call it accordingly.
You are confused about several things here, but one easy way of writing the function is:
int * fun()
{
int * ptr = (int*)malloc(sizeof(int));
* ptr = 115;
return ptr;
}
You are now responsible for freeing the memory, so in main():
int * ip = fun();
printf( "%d", * ip );
free( ip );
The alternative is to pass the address of apointer (a pointer to a pointer) to the function:
void fun( int ** pp )
{
* pp = (int*)malloc(sizeof(int));
** pp = 115;
}
then your code in main() looks like:
int * ip;
fun( & ip );
printf( "%d", * ip );
free( ip );
I think you can see that the first function is simpler to use.
You need to pass the address of the pointer in main if you want to change it:
fun(&ptr);
(and change fun appropriately, of course)
At the moment, it's changing the local variable ptr inside the function, and of course that change doesn't magically appear anywhere else.
You're passing the ptr by value to fun. fun will recieve a copy of ptr which will be modified. You need to pass ptr as int**.
void fun(int** ptr)
{
*ptr = (int*)malloc(sizeof(int));
**ptr = 115;
}
and call it with:
fun(&ptr);
(I also removed the return value from fun since it wasn't used)
The variable int* ptr is passed by value to the function fun. So the value assigned to ptr inside the function using ptr = (int*)malloc(sizeof(int)); will not be reflected outside the function. So when you do a = *ptr; in main() you are trying to use an un-initialized pointer. If you want to to reflect the changes done to ptr outside the function then you need to change the signature of fun to fun(int** ptr) and do *ptr = (int*)malloc(sizeof(int));
Remember that if you want a function to modify the value of an argument, you must pass a pointer to that argument. This applies to pointer values; if you want a function to modify a pointer value (not what the pointer points to), you must pass a pointer to that pointer:
void fun (int **ptr)
{
/**
* Do not cast the result of malloc() unless you are
* working with a *very* old compiler (pre-C89).
* Doing so will supress a valuable warning if you
* forget to include stdlib.h or otherwise don't have
* a prototype for malloc in scope.
*
* Also, use the sizeof operator on the item you're
* allocating, rather than a type expression; if you
* change the base type of ptr (say from int to long),
* then you don't have to change all the corresponding
* malloc() calls as well.
*
* type of ptr = int **
* type of *ptr = int *
* type of **ptr = int
*/
*ptr = malloc(sizeof **ptr);
*ptr = 115;
}
int main(void)
{
int *p;
fun(&p);
printf("Integer value stored at %p is %d\n", (void *) p, *p);
return 0;
}
BTW, you have a type mismatch in your example; your initial declaration of fun returns an int *, but the definition returns void.