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.
Related
This question already has answers here:
Is it safe to keep a pointer out-of-bounds without dereferencing it? [duplicate]
(3 answers)
Closed last year.
Recently, I found an interesting code snippet about array and pointers I didn't understand as a whole.
Here's the code:
void Function(int *B, int *A, int *C, int m)
{
int i;
A++;
for(i = 0; i < m; i++, B++, A++, C++)
*C=*B + *(A-1);
}
int main()
{
int A[] = {3,6,2};
int B[] = {5,7,9};
int C[3];
int n = 3;
int i;
Function(A,B,C,n);
for(i = 0; i < n; i++)
printf("%d ",C[i]);
return 0;
}
Okay, so, in the main, we have two arrays, variable n which we're forwarding to the function. *B, *A, *C are pointers to the first element of an array.
First, we have A++, which means that now, A shows on the second element of an array, which is 7. In the first for loop, i = 0, then *C(first element) = 3 + 5 = 8
Then, i = 1, B is now pointing on 6, A on 9.
Next, the second for loop looks like this:
*C(second element) = 6 + 7 = 13
Till this part, i understood. Now, i incremented to 2, B is showing on 2, but then, we have A++ again, but how A will increment when there is no other element in that array, it's blank basically? When i debugged, in third for loop, A will be 9(A-1), but again, not completely sure how that work.
It's ok to increment a pointer to just past the last element in an array. With such a pointer, you can't dereference it or increment it again (it's undefined behavior).
C is very specific about what you can do with pointer arithmetic without causing undefined behavior, for example disallowing decrementing a pointer to before the first element of the array, or having the pointer increment after the array except for just after the final element. If you have a single object pointed to (rather than an array), it's treated as an array of length 1 for these rules.
Normally, when trying to reference the value of a pointer, one would use &p for the pointer p, so if I have a for loop that iterates through p, a pointer that points to an array, and I want to compare the value of p to that of p+1 I've ran into a bit of an issue. When I type
if(&p < &(p+1){
foo();
}
and in response, I get this error:
error: lvalue required as unary '&' operand
It's worth noting I'm using C89 and the assignment I'm doing doesn't allow me to access the array values directly with arr[value], it's unfortunately required for what I'm writing this for. How do I go about accessing the value of p+1?
The & operator returns the address of its operand. You want the value, which is the * operator for dereferencing.
if (*p < *(p+1)) {
foo();
}
Of course, you have to ensure that you don't do this when p points to the last element of the array, since p+1 points outside the array.
You must use the *p instead &p if you are going to reference the value of pointer 'p'. The '&' operand is the address of 'p', not a value.
So, you must do like this:
if (*p < *(p + 1)){
foo();
}
I suggest one sample below
void foo()
{
printf("foo\n");
}
int main()
{
int arr[5] = {1, 2, 3, 4, 5} ;
int * p = arr;
for (int i = 0; i < 4; i++)
{
if (*p < *(p + 1))
{
foo();
}
p++;
}
return 0;
}
Refer the following C program and while incrementing the pointer (i.e. p), it is correctly incrementing by 4 bytes. While if I try to increment the pointer to pointer (i.e. pp), then same is incrementing by 8 bytes. And I am not understanding why is it happening in this way and may be i have misunderstanding in the concept.
#include <stdio.h>
int main()
{
float a = 5, *p, **pp;
p = &a;
pp = &p;
printf("a=%f, p=%p, pp=%p\n", a, p, pp);
a = a + 1;
p = p + 1;
pp = pp + 1;
printf("a=%f, p=%p, pp=%p\n", a, p, pp);
return 0;
}
output:
a=5.000000, p=0x7ffc93c93374, pp=0x7ffc93c93368
a=6.000000, p=0x7ffc93c93378, pp=0x7ffc93c93370
Pointer arithmetic is done in units of the size of the type that the pointer points to. On your system, sizeof(float) is 4, so incrementing p adds 4 bytes to it. But sizeof(float*) is 8 because it's a 64-bit system, so incrementing pp adds 8 bytes to it.
To append the answer of #Barmar I would like to point out that if you have an array
T a[N];
where T is some type and N is some value then after such a declaration of a pointer like
T *p = a;
The pointer p will point to the first element of the array a. This declaration is equivalent to
T *p = &a[0];
If to increment the pointer p it is naturally to assume that it will point to the second element of the array a that is its value will be the value of the expression &a[1]. S0 you need to add to the original value of the pointer p the value that is equal to the value of the size of an element of the array a that is the value equal to sizeof( T ).
Such a calculation is named the pointer arithmetic.
Thus the expression
p + 1
or
++p
means to add the value sizeof( T ) to the value stored in the pointer p. As a result the pointer expression will point to the next element of the array.
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;
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);