Why is p[0]++ different from *(p)++ in C - arrays

When I tried to execute these codes in C
#include <stdio.h>
int main(void)
{
int arr[] = {10, 20};
int *p = arr;
p[0]++; // *(p)++;
printf("arr[0] = %d, arr[1] = %d",arr[0], arr[1]);
return 0;
}
output: arr[0] = 11, arr[1] = 20
on replacing p[0]++; by *(p)++;
output : arr[0] = 10, arr[1] = 20
Please explain why this is. I know a[i] is equivalent to *(a + i)

The expression:
p[0]++;
basically increments the value at index 0.
While
*(p)++
Increments the pointer to the next address .
Example :
int arr = {10,20};
int *p = arr; // p points to the first element of array, i.e 10
*(p)++; // now p points to the next element i.e 20.

below code can be used:
p[0]++ means = p[0] + 1;
p[0]++ = 10 + 1;
p[0]++ = 11;
You can't do with this same thing with an array, so be careful.
I hope it helps!

Related

Operator and Pointer precedence

Below is the problem I found on the internet.
int main()
{
int a[4] = { 10, 21, 32, 43};
int *p = a + 3;
++*--p;
++*p--;
p[2] += p[1];
for (int i = 0; i < 4; ++i)
printf("%d - %d\t", a[i]);
return 0;
}
//What will be the output?
answer : 10 21 34 77
I understood a lot of things, but the only thing I'm stuck on:
What is the difference between (++*--p) and (++*p--) ?
Shouldn't these two give the same result? Because (*p--) and (*--p) give the same result in the compiler. The compiler I use is Code::Blocks
Because (*p--) and (*--p) give the same result in the compiler.
No, they do not. *p-- decrements p but applies * to the value of p before the decrement. *--p applies * to the value of p after the decrement.
What is the difference between (++*--p) and (++*p--) ?
++*--p decrements p and increments the object it points to after the decrement.
++*p-- decrements p but increments the object it points to before the decrement.
What is the difference between (++*--p) and (++*p--) ?
The difference is that --p decrements p and resolves to the new value of p, whereas p-- decrements p and resolves to the old value of p.
++* works identically on both - performing indirection on p, incrementing the value p points to, and resolving to this new value.
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 10;
/* This prints 9, and `a` is now 9 */
printf("%d\n", --a);
/* This prints 10, and `b` is now 9 */
printf("%d\n", b--);
/* This prints 9 and 9 */
printf("%d %d\n", a, b);
}
Shouldn't these two give the same result? Because (*p--) and (*--p) give the same result in the compiler.
The order here matters, using (*--p) before (*p--) would resolve to the same element twice. Using (*p--) before (*--p) resolves to different elements.
#include <stdio.h>
int main(void)
{
int a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int *p = a + 4;
/* 4 then 4 */
printf("%d ", *--p);
printf("%d\n", *p--);
p = a + 4;
/* 5 then 3 */
printf("%d ", *p--);
printf("%d\n", *--p);
}

accessing C multidimensional array via array syntax vs pointer arithmetic

I'm diving into C again after a number of years. I thought that the following two print statements would have evaluated to the same output, based on other answers I have found; however it does not appear to be the case.
int main()
{
int** arr = malloc(
3 * sizeof(int*)
);
for(int y = 0; y < 3; y++) {
int* subarr = malloc(
3 * sizeof(int)
);
for(int x = 0; x < 3; x++) {
subarr[x] = y * 3 + x + 1;
}
arr[y] = subarr;
}
printf("%d\n", *(&arr[0][0]) + 3);
printf("%d\n", (&arr[0][0])[3]);
}
Could anyone explain what is going on here/what I am missing?
First of all, Let me explain what you are doing (At least for me).
arr[0] = A pointer to array {1, 2, 3}
arr[1] = A pointer to array {4, 5, 6}
arr[2] = A pointer to array {7, 8, 9}
First Case: *(&arr[0][0]) + 3
&arr[0][0] = Address of first element of {1, 2, 3}
*(&arr[0][0]) = 1 // Dereferencing the address
So, It prints 1 + 3 = 4
Second Case: (&arr[0][0])[3]
(&arr[0][0]) = Address of first element of {1, 2, 3}
But the length of array is 3, So you can only access indices up to 2.
So, It is causing undefined behaviour.

I am confused how to understand this code. contains double pointers

I don't understand why the code below changes the array b:
int a[] = { 3, 6, 9 };
int b[] = { 2, 4, 6, 8, 10 };
int **c;
int **d[2];
c = (int **)malloc (b[1] * sizeof(int *));
*c = &a[1];
c[1] = c[0] + 1;
*d = c;
c = c + 2;
*c = b;
c[1] = &c[0][3];
*(d + 1) = c;
d[0][3][1] = d[1][0][0];
d[1][0][2] = d[0][1][0];
I have run this code and found the values of array a and array b but I am unable to understand how these values come.
Array a remains unchanged while b becomes 2, 4, 9, 8, 2. How does this happen?
c = (int**)malloc(b[1] * sizeof(int*)); //int **c[4] ???
c is an array of double pointers *c = &a[1] this means that c[0] has the address of array a's second index. I am not getting the way to interpret this.
The code contains actual statements, therefore it must be part of a function body, hence all declarations herein have automatic storage. It is highly convoluted, with purposely contrived double indirections... Lets analyse it one line at a time:
int a[] = { 3, 6, 9 }; -- a is an array of 3 ints initialized with some explicit values.
int b[] = { 2, 4, 6, 8, 10 }; -- likewise, b is an array of 3 ints initialized with some explicit values.
int **c; -- c is an uninitialized pointer to a pointer to int, that can be made to point to an array of pointers to int.
int **d[2]; -- d is an uninitialized array of 2 pointers to pointers to int, each of which can be made to point to an array of pointers to int.
c = (int **)malloc(b[1] * sizeof(int *)); -- c is set to point to a block of uninitialized memory with a size of 4 pointers to int. In short, c now points to an uninitialized array of 4 pointers to int.
*c = &a[1]; -- The element pointed to by c (aka A[0]) is set to point to the second element of a (aka a[1], with a value of 6). The value of A[0] is &a[1].
c[1] = c[0] + 1; -- The second element in the array pointed to by c (aka A[1]) is set to point to the element after the one pointed to by c[0], hence it points to the third element of a (aka a[2] with a value of 9). The value of A[1] is&a[2]`.
*d = c; -- The first element of d is set to the value of pointer c, which is the address of A[0]. The value of d[0] is &A[0].
c = c + 2; -- The pointer c is incremented by 2, it now points to the third element of the array A allocated with malloc(), A[2].
*c = b; -- The element pointed to by c, A[2], which is itself a pointer, is set to point to the first element of b, b[0]. The value of A[2] is &b[0].
c[1] = &c[0][3]; -- The element after that, A[3], the 4th element of the array allocated by malloc, is set to point to the 4th element of the array pointed to by the element c points to. &c[0][3] is equivalent to c[0] + 3 or &(*c)[3] or simply *c + 3. This element is b[3] which has the value 8. The value of A[3] is&b[3]`.
*(d + 1) = c; -- This is equivalent to d[1] = c; which sets the second element of d to the value of the pointer c, which is the address of the 3rd element of the array allocated wth malloc(), A[2], which points to b[0]. The value of d[1] is &A[2].
d[0][3][1] = d[1][0][0]; -- Let's rewrite these terms:
d[0][3][1] => (&A[0])[3][1] => A[3][1] => (&b[3])[1] => *((b + 3) + 1) => b[4]
d[1][0][0] => (&A[2])[0][0] => (*&A[2])[0] => A[2][0] => (&b[0])[0] => b[0] which is the value 2.
Hence b[4] = 2;.
d[1][0][2] = d[0][1][0]; -- Let's rewrite these:
d[1][0][2] => (&A[2])[0][2] => (*&A[2])[2] => A[2][2] => (&b[0])[2] => (b + 0)[2] => b[2].
d[0][1][0] => (&A[0])[1][0], ie A[1][0] => (&a[2])[0] => *&a[2] => a[2] that has a value of 9.
Hence b[2] = 9;
As a consequence, the array b now has elements { 2, 4, 9, 8, 2 }.
You can run the program:
#include <stdio.h>
#include <stdlib.h>
int main() {
int a[] = { 3, 6, 9 };
int b[] = { 2, 4, 6, 8, 10 };
int **c;
int **d[2];
c = (int **)malloc (b[1] * sizeof(int *));
*c = &a[1];
c[1] = c[0] + 1;
*d = c;
c = c + 2;
*c = b;
c[1] = &c[0][3];
*(d + 1) = c;
d[0][3][1] = d[1][0][0];
d[1][0][2] = d[0][1][0];
printf("a = { ");
for (size_t i = 0; i < sizeof a / sizeof *a; i++)
printf("%d, ", a[i]);
printf("};\n");
printf("b = { ");
for (size_t i = 0; i < sizeof b / sizeof *b; i++)
printf("%d, ", b[i]);
printf("};\n");
return 0;
}

Modifying an integer in an array of integers

If I have a an array of ints, how could I directly edit each int?
int i = arr + 1; // Getting the integer in pos 1
i is just a copy, correct? If I set i = 4, then arr + 1 would still be 1.
Would this work?
int *i = &(arr + 1);
*i = 4;
You should use the array operators:
int i = arr[1];
arr[1] = 4;
Change your code to this:
int *i = arr + 1;
*i = 4;
and it will work. Arrays in C are just pointers to first element in the array.
So this arr + 0 will give address of first element in array and this arr + 1 is an address of second element.
You've got:
int arr[4] = {0, 1, 2, 3};
Want to edit it further?
arr[0] = 42;
// arr[] = {42, 1, 2, 3};
Want to change all of them at once? There's:
for(int i = 0; i < 4; ++i)
arr[i] = i * 2;
// arr[] = {0, 2, 4, 6};
And don't forget memset()!
memset(arr, 42, 4);
// arr[] = {42, 42, 42, 42};
Want to change everything but the first element to 7?
memset(&arr[1], 7, 4 - 1);
// arr[] = {42, 7, 7, 7};
Would you like to know somethin' about pointers? (Here's a more useful link.)
See this? (If you can't, please stop reading this. Thanks!)
int *ptr = &arr[1];
It's equivalent to:
int *ptr = arr + 1;
Which is also equivalent to:
int *ptr = arr;
ptr = ptr + 1;
OK, now that we've got that down, let's show you a more efficient for-loop than the one I did above:
int *ptr = arr;
for(int i = 0; i < 4; ++i)
{
*ptr = i << 2;
// i * 2 == i << 2
++ptr;
}
// arr[] = {0, 2, 4, 6};
Not that you should code like that; the compiler will handle it for you, most likely.
Would you like another answer in the form of a series of questions?
Array indexing operators can do what you need.
arr[3] = 101; //assignment to array
int x = arr[37]; //get value from array
etc.
No need for for that memory arithmetic here..

Incrementing variables using pointers

I'm very new to dealing with pointers, and my C knowledge is fairly small. I'm trying to understand pointers. I wrote the following code to print a list of variables (a to f) like so:
0
1
2
3
4
5
I wrote the following code to do this:
#include <stdio.h>
int main(){
int a,b,c,d,e,f;
int *p;
int i;
a = b = c = d = f = 0;
p = &a;
for (i = 0; i < 5; i++){
*p += i;
printf("%d\n", *p);
p++;
}
return 0;
}
The idea was it works through the variables and increments each by an ever-increasing number (i). I am assuming that as you initialize the variables at the same time, they'd be placed next to each other in memory. However, I get the following output:
0
1
2
3
-1218283607
If I change the for loop to only go from 0 to 3 (i < 4), it works fine, printer 0 1 2 and 3. But when I wish to print the variable f as well, it doesn't seem to set it.
As I said, I'm very new to pointers so I've probably overlooked something silly, but I've been looking through my code over and over, trying to work it out.
Thanks in advance.
There is no guarantee that a, b, c, d, e and f will be adjacent in memory. If you want that sort of guarantee you need to use an array.
#include <stdio.h>
int main() {
int a[6];
int *p;
int i;
a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = 0;
p = &a[0];
for (i = 0; i < 6; i++){
*p += i;
p++;
}
for(i = 0; i < 6; i++) {
printf("%d\n", a[i]);
}
return 0;
}
Here int a[6] is declaring an array named a that can hold six integers. These six integers can obtained via a[0], a[1], a[2], a[3], a[4] and a[5]. You are guaranteed that a[0], a[1], a[2], a[3], a[4] and a[5] are layed out contiguously in memory. Thus the line
p = &a[0];
sets p to the address of the first element. Each increment of this pointer moves us forward one position in the array.
The second for loop shows that first for loops correctly sets a[i] to i for i in {0, 1, 2, 3, 4, 5}. If you run this program you will see
0
1
2
3
4
5
on the console.
You forgot to initialize e. But yes, use a packed array.
It isn't safe to assume that stack variables are arranged in memory in any particular order.
You need to use an array, a struct or possibly a union to gurantee the ordering of your ints.
union {
int ary[6];
struct {
int a;
int b;
int c;
int d;
int e;
int f;
} s;
} u = {0};
p = &u.s.a;
for (i = 0; i < 5; i++){
*p += i;
printf("%d\n", *p);
p++;
}

Resources