Let us assume,
int *p;
int a = 100;
p = &a;
What will the following code actually do and how?
p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);
I know, this is kind of messy in terms of coding, but I want to know what will actually happen when we code like this.
Note : Lets assume that the address of a=5120300, it is stored in pointer p whose address is 3560200. Now, what will be the value of p & a after the execution of each statement?
First, the ++ operator takes precedence over the * operator, and the () operators take precedence over everything else.
Second, the ++number operator is the same as the number++ operator if you're not assigning them to anything. The difference is number++ returns number and then increments number, and ++number increments first and then returns it.
Third, by increasing the value of a pointer, you're incrementing it by the sizeof its contents, that is you're incrementing it as if you were iterating in an array.
So, to sum it all up:
ptr++; // Pointer moves to the next int position (as if it was an array)
++ptr; // Pointer moves to the next int position (as if it was an array)
++*ptr; // The value pointed at by ptr is incremented
++(*ptr); // The value pointed at by ptr is incremented
++*(ptr); // The value pointed at by ptr is incremented
*ptr++; // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value pointed at by ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr; // Pointer moves to the next int position, and then get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault
As there are a lot of cases in here, I might have made some mistake, please correct me if I'm wrong.
EDIT:
So I was wrong, the precedence is a little more complicated than what I wrote, view it here:
http://en.cppreference.com/w/cpp/language/operator_precedence
checked the program and the results are as,
p++; // use it then move to next int position
++p; // move to next int and then use it
++*p; // increments the value by 1 then use it
++(*p); // increments the value by 1 then use it
++*(p); // increments the value by 1 then use it
*p++; // use the value of p then moves to next position
(*p)++; // use the value of p then increment the value
*(p)++; // use the value of p then moves to next position
*++p; // moves to the next int location then use that value
*(++p); // moves to next location then use that value
The following is an instantiation of the various "just print it" suggestions. I found it instructive.
#include "stdio.h"
int main() {
static int x = 5;
static int *p = &x;
printf("(int) p => %d\n",(int) p);
printf("(int) p++ => %d\n",(int) p++);
x = 5; p = &x;
printf("(int) ++p => %d\n",(int) ++p);
x = 5; p = &x;
printf("++*p => %d\n",++*p);
x = 5; p = &x;
printf("++(*p) => %d\n",++(*p));
x = 5; p = &x;
printf("++*(p) => %d\n",++*(p));
x = 5; p = &x;
printf("*p++ => %d\n",*p++);
x = 5; p = &x;
printf("(*p)++ => %d\n",(*p)++);
x = 5; p = &x;
printf("*(p)++ => %d\n",*(p)++);
x = 5; p = &x;
printf("*++p => %d\n",*++p);
x = 5; p = &x;
printf("*(++p) => %d\n",*(++p));
return 0;
}
It returns
(int) p => 256688152
(int) p++ => 256688152
(int) ++p => 256688156
++*p => 6
++(*p) => 6
++*(p) => 6
*p++ => 5
(*p)++ => 5
*(p)++ => 5
*++p => 0
*(++p) => 0
I cast the pointer addresses to ints so they could be easily compared.
I compiled it with GCC.
With regards to "How to increment a pointer address and pointer's value?" I think that ++(*p++); is actually well defined and does what you're asking for, e.g.:
#include <stdio.h>
int main() {
int a = 100;
int *p = &a;
printf("%p\n",(void*)p);
++(*p++);
printf("%p\n",(void*)p);
printf("%d\n",a);
return 0;
}
It's not modifying the same thing twice before a sequence point. I don't think it's good style though for most uses - it's a little too cryptic for my liking.
Note:
1) Both ++ and * have same precedence(priority), so the associativity comes into picture.
2) in this case Associativity is from **Right-Left**
important table to remember in case of pointers and arrays:
operators precedence associativity
1) () , [] 1 left-right
2) * , identifier 2 right-left
3) <data type> 3 ----------
let me give an example, this might help;
char **str;
str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char*
str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
strcpy(str[0],"abcd"); // assigning value
strcpy(str[1],"efgh"); // assigning value
while(*str)
{
cout<<*str<<endl; // printing the string
*str++; // incrementing the address(pointer)
// check above about the prcedence and associativity
}
free(str[0]);
free(str[1]);
free(str);
Related
Suppose a and b are pointers,
My understanding is *--a = *--b means subtract 1 from a and b using pointer arithmetic, then dereference a and b and set them equal.
Is this equivalent to
--a;
--b;
*a=*b
Similarly, what is
*a++ = *b++;
equivalent to?
*––a = *––b
is logically equivalent to
tmpa = a - 1
tmpb = b - 1
*tmpa = *tmpb
a = a - 1
b = b - 1
with the caveat that the updates to a, b, and *tmpa can occur in any order, and those updates can even be interleaved. It’s also possible for the implementation to skip the temporaries and update the pointer values immediately:
a = a - 1
b = b - 1
*a = *b
but that’s not required or guaranteed. Similarly,
*a++ = *b++
is logically equivalent to
tmpa = a
tmpb = b
*tmpa = *tmpb
a = a + 1
b = b + 1
with the same caveats about the ordering of the updates to a, b, and *tmpa. Again, the implementation may skip using temporaries and evaluate it as
*a = *b
a = a + 1
b = b + 1
but again that’s neither required nor guaranteed.
*a++ = *b++;
dereference b and assign it to where a points. The ++ is the postfix operator, so the current value of *b will be assigned to *a, then both will be incremented.
If you keep this in a while loop, all the characters from b will be copied to a including the \0. This continues as long as *a++ = *b++ is not \0, at which time loop terminates.
while(*a++ = *b++);
Example :
#include <stdio.h>
int main()
{
char a_arr[30] = {0};
char b_arr[] = "Hello,World";
char *a = a_arr;
char *b = b_arr;
while(*a++ = *b++);
puts(a_arr);
puts(b_arr);
return 0;
}
Example
uint8_t *a = 1030; // POINTS TO ADDRESS 1030
uint8_t *b = 1020; // POINTS TO ADDRESS 1020
printf("%d", *(--a)); // PRINTS VALUE ON ADDRESS 1029
printf("%d", *(b++)); // PRINTS VALUE ON ADDRESS 1021
*(--a) subtracts one byte(one address) because pointer a points to one byte(it is uint8_t). After subtraction, it will read value from address.
*(--something) you can write as
uint32_t *c = 1050;
c -= 1; // SUBCTRACTS 4 BYTE ADDRESS FROM POINTER c
print("%d", *c);
Why 4 bytes you may ask? Because pointer c points to four byte(uint32_t or int32_t) data. You can get size of data in bytes with sizeof(variable).
In your case, lets say pointer a points to address 40. Pointer b points to address 50.
Address 39 holds value 1
Address 40 holds value 2
Address 50 holds value 10
Address 51 holds value 11
uint8_t *a = 40;
uint8_t *b = 50;
printf("%d", *(--a));
printf("%d", *(b++));
First printf will print value 1. Second printf will print value 50.
After printf pointer a points to address 39 and pointer b points to address 51
Reason? In first printf, it will first subctract one address(again, one because it points to one byte value), and then it will dereference value(that is why we use * for reading the value from pointer address).
In second printf, it will first dereference value and then move pointer one address up.
I have a problem with understanding the use of pointers in my C-program. The program is designed to print out all elements in the array. The most confusing part is the for-loop that doesnt seem to make sense for me. What is the value of p from the beginning? How does the loop stop if the condition p < a + n always is true?
void element(int a[], int n)
{
for (int *p = a; p < a + n; p++)
printf("%d ", *p);
}
int main()
{
int f[5] = {1, 2, 3, 4, 5};
element(f, 5);
}
For your code, p points to a[0], then to a[1], then a[2] and so on.
The condition p < a + n is terminating because when you increment p, it makes the pointer p move from a[0] to a[1] and so on, thus increasing its value and a+n is 1+5=6.
So when p reaches 5, condition becomes false in next iteration.
p is a pointer to an integer (the asterisk in the declaration is what makes it a pointer)
p Starts off pointing to the initial element of array a, which in this context is also a pointer
Each iteration advances p by one integer position in memory
The loop ends once p crosses over past the end of the array.
To learn more about the a + n expression read about pointer arithmetic.
The structure of a for loop is for(/* do first */; /* continue doing while this is true */ ; /* do after the loop body */ ).
Lets apply that to your for (int *p = a; p < a + n; p++).
/* do first */ int *p = a /* introduce a pointer-to-int, initialised to a */
/* continue while this is true */ p < a + n /* p is less than p+n, still within the array */
/* do after the loop body */ p++ /* increment the pointer by one "pointed-to" */
Note that a decays into a pointer to an int containing the address of the array, or the address of element at index 0 within that array and that p+n is the address AFTER the last element in the array, which is allowed to be compared to, but not accessed.
I found an example of a pointer to array which to me doesn't make much sense, I was wondering if anybody would be able to help me?
int a[5] = 0,1,4,89,6;
int *p = a; 'p points at the start of a'
p[3] = 1; 'a[3] is now 6'
I'm not sure how the third line, p[3] = 1, works and how it causes a[3] = 6. Thanks for the help in advance.
It is bit incorrect. a[3] is 1, not 6.
Here are explanation line by line:
int a[5] = 0,1,4,89,6;
int *p = a; //'p points at the start of a'
p[3] = 1; //'a[3] is now 1 not 6'
First line initialize the array. I think there should be {} around numbers, but if compiles with you then is OK. This is how I believe it should be:
int a[5] = {0,1,4,89,6};
Second line create pointer to int p and initialize it to the address of a. Arrays and pointers are closely related in C, so now, you have 2 variables a and p pointing to one and same memory address.
Third line - you set p[3] to 1, this time you access p as array of int (it is possible because of that relationship between arrays and pointers). Because p and a points in same memory address, this means a[3] is now 1
Also remarks are incorrect, must be /* */ or //.
UPDATE :
David's comment is very important.
Arrays are sequential reserved memory capable to store several array values, in your case 5 int's.
A pointer is a pointer and may point everywhere they can point to int variable:
int a = 5;
int *b = &a;
or they can point to array as in your case. In both cases you will be able to use [], but in case it points to single value, any array subscript greater than zero will be wrong, e.g.
int a = 5;
int *b = &a;
*b = 4; // OK.
b[0] = 4; // OK.
b[1] = 4; // compiles correctly, but is **wrong**.
// it will overwrite something in memory
// and if program not crash,
// it will be security hole.
int x[10];
int *y = x;
*y = 4; // works correctly for y[0],
// but makes it difficult to read.
y[0] = 5; // OK
y[9] = 5; // OK
y[10] = 5; // compiles correctly, but is **wrong**.
// it is after last element of x.
// this is called **buffer overflow**.
// it will overwrite something in memory
// and if program not crash,
// it will be security hole.
UPDATE :
I recommend you check this article
http://boredzo.org/pointers/
void inc(int *p) {
p += 1;
}
int main() {
int x = 5;
inc(&x);
printf("x = %d\n", x);
return 0;
}
I've figured that this code doesn't increase the value of x.
It works when I change
void inc(int *p) {
p += 1;
}
to
void inc(int *p) {
*p += 1;
}
Kind of got confused with pointers right now.
Can someone help me?
Thank you in advance!
The difference between the two pieces of code is the difference between increasing the address that the pointer contains and changing the actual value.
The first piece of code: p += 1; increases the address that p is pointing to by one. For instance if x is at address 124, then p was first equal to 124 and is now increased to 125 (in a simple scenario, realistically this would increase by more as p is an integer pointer and thus the increase would be more than 1 byte).
The second piece of code: *p +=1; first dereferences the address in p and adds one to the value currently stored in that address. For instance if x is at address 124 and is of the value 42, then p equals 124, but *p is the deferenced pointer and is equal to 42. You can then assign a new value to *p to make the value at address 124 (i.e. the value of x) equal to 43.
EDIT: As mentioned by #Bathsheba, pointers are passed by value to function calls. This means that if we were to do the following, the original pointer y would remain unchanged, whereas the address p is pointing to does change as mentioned above.
void inc(int *p) {
p += 1;
}
int main() {
int x = 5;
int *y = &x;
inc(y);
return 0;
}
As for your second question on structs. Structs pointers still contain the address of the struct in memory, but the 'arrow notation' you refer to will implicitly do the dereferencing of the fields for you.
Can anyone explain the reason behind the second output? Also what is the difference between solving using int pointers and char pointers?
The second answer is coming out to be 0.
int main()
{
char arr[] = "geeksforgeeks";
char *ptr1 = arr;
char *ptr2 = ptr1 + 3;
printf ("ptr2 - ptr1 = %d\n", ptr2 - ptr1);
printf ("(int*)ptr2 - (int*) ptr1 = %d", (int*)ptr2 - (int*)ptr1);
getchar();
return 0;
}
Pointers of some type T point to objects of type T.
For example
int a[] = { 1, 2 };
int *p = a;
If you increase a pointer as for example
++p;
or
p = p + 1;
(take into account that these statements are equivalent) it will point to the next object of type T that follows the current object. So the value of the pointer will be increased by sizeof( T ) that to provide that the poiner indeed will point to the next element.
In the example above sizeof( int ) is (usually) equal to 4. So the value of the pointer will be increased by 4.
If you write
int a[] = { 1, 2 };
int *p = &a[0]; // the same as int *p = a;
int *q = &a[1];
then expression q - p will be equal 1 but the difference between the values stored in p and q will ve equal to sizeof( int ). p points to the first element of the array and q points to the second element of the array. It is so-called pointer arithmetic.
As for your result with subtracting int pointers then the behaviour is undefined. According to the C++ Standard
Unless both pointers point to elements of the same array object, or one
past the last element of the array object, the behavior is undefined
In your case int pointers do not point to elements of the same array. That they would point to the elements of the same array at least the difference of their values shall be equal to sizeof( int )
It's happen because char size is 1-byte, when int is 32Bit (4byte) variable
Edit keep pointer in the original array and ensure correct alignement to avoid undefined behaviour (see comment of Matt McNabb)
Because 3 < sizeof(int).
In pointer arithmetic, (int *) ptr2 - (int *) ptr1 gives real_addr_of_ptr2 - real_addr_of_ptr1) / sizeof(int) = 3 / 4. As it is integer division => 0 - this is not specified by C++ but is current implementation.
If you use : char *ptr2 = ptr1 + 8;, you will get : (int*)ptr2 - (int*) ptr1 = 2
As there are more than 8 characters in array, it can work, provided the original array is correctly aligned. To be coherent with the specs, it should have been declared :
union {
char arr[] = "geeksforgeeks";
int iarr[];
} uarr;
char *ptr1 = uarr.arr;