I'm new to learning programming by the way so don't be too harsh. Why exactly am I getting this warning and how do I fix it?
Here's the full code:
#include <stdio.h>
int main()
{
int a; // this declares the 'a' variable
int *ptr_a; // this declares the pointer variable
printf("a:");
scanf("%d", &a);
printf("a is %d\n", a); // this prints the value of 'a' that is read from the keyboard
printf("the address of the pointer is %p\n", ptr_a); // this prints the address of the pointer
ptr_a = &a; // this points the pointer to the 'a' variable
*ptr_a = *ptr_a + 5; // this modifies the 'a' variable with its pointer
printf("the value of the modified a is %d\n", a); // this prints the modified value of 'a'
printf("the address of the modified pointer is %p\n", ptr_a); // this prints the modified address of the pointer
return 0;
}
This line:
printf("the address of the pointer is %p\n", ptr_a); // this prints the address of the pointer
does not print the address of the pointer. It attempts to print the value of ptr_a. Since ptr_a has not been initialized, the compiler warns you that you are using it uninitialized.
If you printed the address of ptr_a, with:
printf("the address of the pointer is %p\n", (void *) &ptr_a);
Then the compiler will not warn use, because this does not use the value of ptr_a (which is not initialized), just its address (which is set when ptr_a is created).
After the line ptr_a = &a;, ptr_a is initialized with a value, and a line like this:
printf("The address of a is %p.\n", (void *) ptr_a);
will print the value without a compiler warning.
The warnings are to take seriously, even though they may seem unnecessary at times, doing so will create good programming habits, you can initialize the pointer to NULL then reassign it later, when you need to:
int *ptr_a = NULL;
However what's triggering the problem here is the fact that you are printing the value of the pointer not its address, which would be perfectly fine as it still has an address even when uninitialized, it only has a value when you assign it the address of a variable or otherwise make it point to some memory location.
If you want to print the address of the pointer you'll need &ptr_a and for good measure, being pedantic I'll admit, cast it to void* as %p specifier expects a pointer to void, not to int:
printf("the address of the pointer is %p\n", (void*)&ptr_a);
Related
I am writing code to learn what happens when pointers are passed as arguments in a function.
void ptrTest(int **arg_ptr);
int main() {
int some_var = 5;
int *ptr1;
ptr1 = &some_var;
printf("Address of some_var: %u\n\n", &some_var);
printf("Value stored in *ptr1 (references to some_var): %u\n", ptr1);
printf("Address of *ptr1 variable: %u\n\n", &ptr1);
ptrTest(ptr1);
}
void ptrTest(int **arg_ptr){
printf("Value stored in **arg_ptr (references to some_var): %u\n",arg_ptr);
}
The result is as follows:
Address of some_var: 3119323004
Value stored in *ptr1 (references to some_var): 3119323004
Address of *ptr1 variable: 3119322992
Value stored in **arg_ptr (references to some_var): 3119323004
I am surprised that arg_ptr takes the value that references to address of some_var. I was expecting **arg_ptr to point to *ptr and store the value of 3119322992(referencing to the address of *ptr).
When I test pointer to pointer outside of a function, it does behave in this exact manner. Why it differs for pointer to pointer as an argument baffles me.
Can you explain to me what's happening here?
First of all what is a pointer? A pointer in C/C++ is just like any other variable with a type like int, char etc. But speciality of this variable is that unlike other variable it just hold the address of a memory location. Again that memory location also might be a pointer variable or any other regular variable( int or char).
Now what is pointer of pointer? A variable who can store the address of a pointer variable and that pointer variable might holding the address of another variable like:-
int i = 10; //`i` is assign with a value 10 and `i` has its own address which we can get by `&i`;
int *ptr1 = &i;// now ptr1 is pointer to `i` means ptr1 is assign with the
//address of `i` hence if we dereference the address of *ptr1 we will get the value stored at that memory location
Now in your case
void ptrTest(int **arg_ptr){
printf("Address store in of **arg_ptr: %u\n",arg_ptr);
}
So here it will work like below
int **arg_ptr = ptr1;//Wrong, `ptr1` is assign to `arg_ptr`, which is wrong because `arg_ptr` is a pointer to pointer type
So here you should store the address of a pointer but you are storing the address of a variable int which is i.
Because address of i has been assign in statement int *ptr1 = &i; to ptr1.
The correct assignment would be
arg_ptr = &ptr1; //address of a pointer not address of a int variable.
Now first dereferencing:-
*arg_ptr; //value of a pointer ptr1 that means address of `i`
*(*arg_ptr); or **arg_ptr;// we further dereferenced the address of ptr1 here, which is value 10
Now you should call your function like below:-
ptrTest(&ptr1);// address of a pointer.
ptrTest expects an argument of type int ** but you are passing int*. Your compiler should complain. You need to pass the address of ptr to the function.
ptrTest(&ptr1);
Apart from that you should use %p specification to print address.
printf("Address of some_var: %p\n\n", (void*)&some_var);
When I compile your code I get a long list of errors:
"test.c", line 11: warning #2181-D: argument is incompatible with
corresponding format string conversion
printf("Address of some_var: %u\n\n", &some_var);
^
"test.c", line 12: warning #2181-D: argument is incompatible with
corresponding format string conversion
printf("Value stored in *ptr1 (references to some_var): %u\n", ptr1);
^
"test.c", line 13: warning #2181-D: argument is incompatible with
corresponding format string conversion
printf("Address of *ptr1 variable: %u\n\n", &ptr1);
^
"test.c", line 14: warning #2167-D: argument of type "int *" is incompatible
with parameter of type "int **"
ptrTest(ptr1);
^
"test.c", line 18: warning #2181-D: argument is incompatible with
corresponding format string conversion
printf("Value stored in **arg_ptr (references to some_var): %u\n",arg_ptr);
Let's rewrite this code so it compiles without errors and is perhaps a little clearer:
#include <stdio.h>
void ptrTest(int **arg_ptr)
{
printf("Value stored in arg_ptr (points to ptr1): %#p\n", arg_ptr);
printf("Value pointed to by arg_ptr (i.e. *arg_ptr - should be same as ptr1): %#p\n", *arg_ptr);
printf("Value pointed to by *arg_ptr (i.e. **arg_ptr - should be same as some_var): %d\n", **arg_ptr);
}
int main()
{
int some_var = 5;
int *ptr1;
ptr1 = &some_var;
printf("some_var: %d\n", some_var);
printf("Address of some_var: %#p\n\n", &some_var);
printf("Value stored in ptr1 (should be address of some_var): %#p\n", ptr1);
printf("Address of ptr1 variable: %#p\n\n", &ptr1);
ptrTest(&ptr1);
}
What got changed:
Used signed int format in printf (%d) instead of unsigned format
(%u).
Used pointer format in printf (%p) when printing pointers.
Added code to ptrTest to follow arg_ptr all the way back to the
base target of the pointer chain.
Added code to print the value of some_var
Changed the wording of the output to clarify what's being shown, and which values should match up.
The new version compiles without errors (HP-UX default C compiler).
When the new version is run the following output is printed:
some_var: 5
Address of some_var: 0x7fffecd0
Value stored in ptr1 (should be address of some_var): 0x7fffecd0
Address of ptr1 variable: 0x7fffecd4
Value stored in arg_ptr (points to ptr1): 0x7fffecd4
Value pointed to by arg_ptr (i.e. *arg_ptr - should be same as ptr1): 0x7fffecd0
Value pointed to by *arg_ptr (i.e. **arg_ptr - should be same as some_var): 5
Now you can follow the chain of pointers forward and back to see which pointer points to which value, and how they all link up.
Best of luck.
I'm slightly confused between these two pieces of code:
version 1: (gives warnings after compiling)
int func(int *ptr2)
{
*ptr2 += 1;
}
int main()
{
int a = 5;
int *ptr = &a;
printf("Address of a: %x\n", a);
printf("Before: %x\n", ptr);
func(&ptr);
printf("After: %x\n", ptr);
return 0;
}
Output:
Address of a: 5770a18c
Before: 5770a18c
After: 5770a18d
version 2:
int func(int **ptr2)
{
*ptr2 += 1;
}
int main()
{
int a = 5;
int *ptr = &a;
printf("address of a: %x\n", &a);
printf("Before: %x\n", ptr);
func(&ptr);
printf("After: %x\n", ptr);
return 0;
}
Output:
Address of a: cc29385c
Before: cc29385c
After: cc293860
If I'm understanding pointers in C correctly when we pass by reference, we are creating a pointer to that location. This allows us to change the value at the address held by the pointer through the dereference operator.
However, if we want to change the value held by a pointer, we use a pointer to a pointer. We pass the address of the pointer and create a new pointer to hold said address. If we want to change the value, we use the dereference operator to access our pointer's (defined elsewhere) value.
Hopefully I'm on the right track, but I'm struggling to visualize what's happening with version 1 specifically. Mainly, I'd just like to understand the difference in make-up and output between these two programs. I assume version 1 is still a pointer to a pointer, but why are the incremented values different between both programs? If version 1 is successfully incrementing ptr's value (which I suspect is not), why is that I cannot find code with the same syntax? I think I'm missing something fairly trivial here... Any help is appreciated
Based on your output, you appear to be compiling for a 32-bit system where addresses and int are of that size.
When you increment the value at *ptr with that type being int, it will simply add 1.
When *ptr resolves to an int* then it will increment by sizeof(int) because the value at the current address in this case is 4 bytes long, so we have to increase the address by the number of bytes that an int consumes so that we're pointing at the next int. Note that doing this is only valid if you actually have allocated memory at the subsequent address.
Generally you pass a T** when the callee needs to modify the address to point to - such as say, the callee performs a malloc() to allocate space for the pointer.
&ptr is a pointer to a pointer, but what is passed to func() is a pointer to int converted from &ptr in implementation-defined manner. Then, *ptr2 += 1; is incrementing int and add 1 to what is pointed by ptr2 (the pointer ptr in main(), which eventually have the same reepresentation as `int in your system).
In version 2, the pointer to a pointer is correctly passed to func(). Therefore, pointer aritimetic is performed and the size of int is added to the address.
Note that you invoked undefined behavior by passing data having wrong type to printf(). The correct way to print pointers is like this:
printf("Before: %p\n", (void*)ptr);
As you see, cast the pointer to void* and use %p specifier.
I try to use the change() function to change the content of y.
I want to ask why y cannot change when I remove the * when assigning x to "abc"?
Also, I found that &*x is the same as &y, does that mean the address of pointer x is assigned to be the same as the address of the content that *y pointed to? Also, why &x does not equals to "abc"?
My Code:
void change(char *x) {
*x = "abc";
printf("S3: %x\n", &x);
printf("S4: %x\n", &*x);
}
int main() {
char *y = "def";
printf("S1: %x\n", &y);
printf("S2: %x\n", &*y);
change(&y);
printf("result: %s\n", y);
return 0;
}
There are many issues in your code, to point out some of them
y points to a string literal. Any attempt to modify a string literal is undefined behaviour.
To print an address, use %p format specifier, with a cast to (void*) for the argument, Using incorrect type of argument is undefined behaviour. Similarly, to print a char, you need %c, to print a string you need %s. Read more here
Inside change() function, *x is of type char, and you're trying to assign a pointer (base address of the string literal "abc") to it.
Enough!! Ask your compiler to tell you 'bout the rest. (In other words, please enable compiler warnings and try to fix the reported issues.)
why &x does not equals to "abc"?
Because &x gives address of x not value it points to . To get value you need *x.
y can't be changed because it points to string literals which is constant . Any try to change it will cause UB.
does that mean the address of pointer x is assigned to be the same as the address of the content that *y pointed to?
Pointer x has address of pointer y as you pass in function the address of y as argument.
You have to read more about pointers and parameters passing.
A pointer is a variable that holds the address in memory of another variable.
When you refer to a variable in your code the compiler use the value of such variable, for this reason when you refer to a pointer you'll get its content that is an address.
The operator & give back the address of a variable, so in the snippet:
int a = 10;
int *p = &a;
The pointer p will hold the memory address of variable a. If we use the operator * on p we will get the content of the memory address hold by a:
printf("%d", *p);
Will print 10.
If we write &*p, while it is not fully correct and many compilers will even issue a warning, we are getting the value pointed to by the pointer, and than requiring the address of that content, that is to have back again the address of data that is the content of the pointer.
Now the functions, when you pass a parameter in a function a copy of the variable is pushed on the stack from where will be accessed inside the function.
These values are local and any change made to them is lost when you leave the function. Of course if you pass a pointer, the address of your variable, then change the value using the pointer you can reflect the change on the real variable.
But you made a big error in your code, while you are declaring a pointer to char in your function proto:
void change(char *x)
You are passing change(&y); that is a char ** (y is a char *, &y is a char **). You should have got a lot of warnings for that.
Anyway the concept is correct on the caller side, you pass the address where is stored the address of your string, changing it y will point to the new string. It is perfectly legal because you're updating a pointer with another constant string (not changing a constant string that is illegal).
But you need the address of the pointer to the string, your function must be:
void change(char **x)
{
*x = "abc";
printf("S3: %p\n", (void *)&x);
printf("S4: %p\n", (void *)&*x);
}
int main(int argc, char *argv[])
{
char *y = "def";
printf("S1: %p\n", (void *)&y);
printf("S2: %p\n", &*y);
change(&y);
printf("result: %s\n", y);
return 0;
}
Last use the correct formatting in printf for pointer it is %p.
it should be change(y) not change(&y), change(&y) is address of *y not address in y. So y gives address of first character in a string, where &y gives address to y not address to first string.
HTH
Consider the following code
#include<stdio.h>
int main()
{
int a[5];
int *ptr=a;
printf("\n%u", &ptr);
++ptr;
printf("\n%u", &ptr);
}
On Output I'm getting same address value, Why pointer address is not incrementing.
The pointer is being incremented. The problem is that you are looking at the address of the pointer itself. The address of a variable cannot change. You mean to look at the value of the pointer, that is, the address it stores:
printf("\n%p", ptr);
On Output I'm getting same address value, Why pointer address is not incrementing.
The value of ptr is different from address of ptr.
By using ++ptr;, you are changing the value of ptr. That does not change the address of ptr. Once a variable is created, its address cannot be changed at all.
An analogy:
int i = 10;
int *ip = &ip;
++i; // This changes the value of i, not the address of i.
// The value of ip, which is the address of i, remains
// same no matter what you do to the value of i.
Let's go through the basics.
When you declare a pointer variable, you use a * with the type of whatever is being pointed to.
When you dereference a pointer (take the value this pointer is pointing to), you put * before it.
When you get the address of something (an address which can be stored in a pointer variable), you put & before whatever you're trying to get the address of.
Let's go through your code.
int *ptr=a; - ptr is a pointer-to-int, pointing to the first element of a.
printf("\n%u", &ptr); this prints the address of ptr. As ptr is a pointer, &ptr is a pointer-to-pointer. That is not what you wanted to see (as I understand), and you'd need to remove &.
++ptr; you inscrease the value of ptr, which is all right, but
printf("\n%u", &ptr); will still output the same thing, because although the contents of the pointer ptr have changed, its address has not.
So, you just need to replace each of the printf calls with printf("\n%u", ptr); to get the desired results.
#include<stdio.h>
int main(void)
{
int *pc;
*pc=100;
printf("\n Address of Pointer : %d",pc);
printf("\n Contents of Pointer : %d",*pc);
}
When I run the code in eclipse, it is saying "Pointers.exe has stopped working". What is the error?
Assigning a value to *pc is particularly dangerous. If pc contains the valid memory address , then the assignment
*pc = 100;
will attempt to modify the data stored at that address.
If the location modified by this assignment belongs to the program, it may behave erratically; if it belongs to operating system, the program will most likely crash.
Your compiler should raise a warning that pc is uninitialized.
Change it to:
int a;
int *pc;
pc = &a;
*pc = 100;
Your pc pointer was not initialized in your program.
Moreover the way your are printing a pointer value is incorrect, use this:
printf("\n Address of Pointer : %p", (void *) pc);
You forgot to point pc to somewhere useful. When you write
int *pc;
The compiler creates a pointer for you. The pointer points somewhere in memory, and you have no way of knowing where. Chances are, it points to a bad place in memory. When you overwrite it with *pc=... you overwrite a place in memory that shouldn't be overwritten.
So you need to have pc point somewhere.
int a, *pc=&a;
will do the trick. Now the compiler prepares an int for you then and you point pc to it. That way, when you write through the pointer, nothing bad will happen - you're writing on an area of memory that you know is safe.
Another way to initialize pc is like so:
int *pc = (int*)malloc(sizeof(int)); // Allocate an integer on the heap
Now *pc=100; will also work. Just don't forget to free(pc) when you're done.
You have:
int *pc;
*pc=100;
When you define the pointer to integer pc above, this pointer is not initialized, so it points to some memory that you have not allocated and you have not the right to access.
So your executable is crashing.
Just use a valid pointer, e.g. you can allocate some heap memory using malloc(sizeof(int)) (and later release it using free()), or just use stack-based memory for local automatic variables, e.g.:
/* An integer stack-allocated variable */
int n = 64;
/* Pointer to that integer */
int * pn = &n;
/* Change its value */
*pn = 100;
Moreover, to print an address, considering using the %p specifier for printf().
e.g.:
#include <stdio.h>
int main(void)
{
int n = 64;
int *pn = &n;
printf("n (before): %d\n", n);
*pn = 100;
printf("n (after): %d\n", n);
printf("Address of n: %p", (void *)pn);
return 0;
}
Output:
n (before): 64
n (after): 100
Address of n: 003AF7CC
Pointers need to POINT! A pointer is a variable that contains the adress of another variable.
int *pc;
This pointer contains some garbage value. Who knows what was in that memory before. The adress that it's pointing to could be an adress of memory that is occupied by another program. You need to assign a valid adress to a pointer if you want to change the value in that adress.
If you want to calculate sum of all the members of an array you would have to initialize the variable sum to 0 because it could contain other values.
The same is with pointers. They have to contain a valid adress of a variable if you want to modify the value.
Your program would work if you comment line *pc = 100;. You can display the adress of an uninitialized pointer but the program will crash if you try to change the value in that adress.