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
Related
When we declare a pointer to any integer say we declare it like
int i=5;
int *p=&i;
We use *p to get the value 5 and if we want the address we use p without asterisk sign to get the address. But in case of character array, when we say
char *str="HELLO";
We simply use str to get "HELLO" as output in printf function. Like this,
printf("%s",str);
Here we used str without asterisk.
Why aren't we getting an address and instead getting "HELLO" as output here while we get address in case of pointers to integers when we use the pointer variable without asterisk?
Okay first of all int *p=5; is wrong! you cant do that in the declaration of a pointer. at That time the pointer expects an adress. You should do int *p; and then *p = 5; to assign the value to it.
printf("%s",str); // prints the value of the variable, because its a pointer.
printf("%s",*str); // the * will cause to a segmentation fault
int *p // the * there is just used to tell the compiler that you are declaring a pointer of type integer.
/* another scope after declaring your pointer */
*p //is used to get value of a pointer variable.(dereference it)
&p //is used to get the adress of a pointer variable.
p //contains an adress.
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);
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.
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.
C Language:
If (p) is a pointer declared as follows:
int a=5, *p;
p = &a;
What does *p will print?
*p won't "print" anything; that's just an expression that de-references the pointer, and produces whatever int value it points at.
You can print it with:
printf("*p=%d\n", *p);
and it will print 5 in your program since p points at a, and the value of a is 5.
The %d is important, it tells printf() to expect an int value, and to format that into a string for printing.
You can also print the pointer itself:
printf("p is %p, a is at %p\n", p, (void *) &a);
this will print the same address twice. The %p format specifier is used for printing addresses.
p is a pointer pointing to an int, *p will be the value of the variable. In this case a. Just for simplicity, you can think of & as the address of, * as the content of pointer as this post The 5-minute Guide to C Pointers points out.
remember a and p are only names, they stands for a variable. Assume the address of a is 1024(which is hardly the real case). Their relation is illustrated as below. The value of a is 5 , When we use p = &a, we assign the address of a, which is 1024 to p. *p will retrieves the value of the address p pointer to, which is what you're looking for: 5.
pic http://cizixs.u.qiniudn.com/pointer
If you want to print the vale, #unwind gives the answer.
Here is a tutorial that might clarify c pointer for you.
p is a pointer to an int. That means it can point to an address, in which an int will be stored.
Writing
p = &a
you set the pointer to point in the address in which integer a is stored.
When you try to print *p, you will get the value that is stored in the address that pointer p points. So you will get 5.
Keep in mind that operator & returns the address of a variable. So &a will return the address of the variable a . Also, when you want to get the value of the variable that is stored in address, if you have a pointer who points ins this address, you use the dereference operator, *. Hence, *p returns the value that is stored in the address that p points to.
p = &a;
p is pointer to a. i.e p holds address of a. and
*p
will give value of a. as & is used to get the address of a variable, * is used for dereferencing a pointer i.e. to get the value of the variable to which the pointer points.