Pointers in C — adding 1 - c

I have a question about pointers. I am beginning to grasp the concept, but this particular piece of code is threatening that understanding, and I just want to clear it up.
Please note line "B", which is printf("ptr + %d = %d\n",i, *ptr++); /*<--- B*/
I was under the impression that, since *ptr was initialized to &my_array[0], then *ptr++ (which would translate to "whatever is at the address stored in ptr, add one to it") would print out 23, which is the value at my_array[1].
Yet, it prints out the value at my_array[0], which is 1.
I'm confused as to whether the ++ adds to the address itself (like, 1004 becomes 1005) and, since the integer takes up about 4 bytes of space, it would fall into the range of my_array[0] (because that value, 1, would take up addresses 1001, 1002, 1003, 1004, and since my_array[0] starts out at 1001 and only goes up to 1002, then *ptr++ would still print out my_array[0], which is 1)...
or...
Whether *ptr++ goes from my_array[0] (which is just *ptr) to my_array[1] *ptr++, which is what I originally thought.
Basically, please explain what *ptr++ does to this program in particular. Please explain it to me as though I was a five year old.
I really appreciate it, and here's the code:
#include <stdio.h>
int my_array[] = { 1, 23, 17, 4, -5, 100 };
int *ptr;
int main(void)
{
int i;
ptr = &my_array[0]; /* point our pointer to the first
element of the array */
printf("\n\n");
for (i = 0; i < 6; i++)
{
printf("my_array[%d] = %d ", i, my_array[i]); /*<-- A */
printf("ptr + %d = %d\n", i, *ptr++); /*<--- B*/
}
return 0;
}

Change this:
printf("ptr + %d = %d\n",i, *ptr++); /*<--- B*/
to this:
printf("ptr + %d = %d\n",i, *(++ptr)); /*<--- B*/
When you use the postfix version if the increment operator, the value of the object before the increment is returned by value by the expression. The prefix increment operator (which the second set of code in this answer uses) will return the incremented object by reference.

*ptr++ will increment after the printf. You should use *(++p).

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);
}

Use of &ampersand and square bracket in printf

I came across the following code in an MCQ quiz,
#include <stdio.h>
int main()
{
int j =2, k =4;
printf(&j["Programming"], &k["Theory"]);
k = j ^ 3;
if (k == j)
printf(&k["Practical"], "Trytosolve");
else
printf(&j["Problem creation"]);
return 0;
}
where ampersand is used in the beginning itself and outside the quotes ("") of printf statement. I am only aware of the traditional use of printf statement and its format specifiers.
I tried to run this code, and it showed no error but this warning:
format not a string literal and no format arguments
and the following output
ogrammingoblem creation (this was one of the options in multiple choices)
I tried to search for such use, but could not find. Can someone explain this use of & and square brackets?
Say we have an array a and a variable i of integral type, then a[i] is equivalent to *(a + i), i.e. we can obtain the ith element of a by decaying a into a pointer to its first element, incrementing that pointer by i and dereferencing the result. This it true because arrays occupy contiguous addresses in memory.
Now, as it turns out, i[a] is also equivalent to a[i], this is more of a "trick" that nobody (to my knowledge) would ever use in production. It's sort of intuitively justifiable that this would be the case because a[i] == *(a + i) == *(i + a) == i[a].
So then, &j["Programming"] == &(*(j + "Programming")). And because dereferencing a pointer and then taking it's address is a noop, this is j + "Programming" == "Programming" + j == "ogramming", because strings are just arrays of characters.
Same for the other branch, which is executed because 2 ^ 3 == 1 != 2.
Maybe this example program will show you the math behind the scenes:
#include <stdio.h>
int main(void)
{
int j=2, k=4;
char *p1 = "Programming";
// Print the address of j
printf("&j = %p\n", &j);
printf("\n");
printf("Pointer arithmetic\n");
// Print the address of "Programming"
printf("p1 = %p\n", p1);
// Print the value of j
printf("j = %8d\n", j);
// Print the result of the pointer computation
printf("&j[\"%s\"] = %p\n", p1, &j[p1]);
// Print the result of the equivalent pointer computation
printf("p1 + j = %p\n", p1 + j);
printf("\n");
printf("Print strings\n");
// Print "Programming" after skipping the first two letters
printf("&j[\"%s\"] = %s\n", p1, &j[p1]);
// Print "Programming" after skipping the first two letters
printf("p1 + j = %s\n", p1 + j);
return 0;
}
Output
&j = 0x7fffb3325aa8
Pointer arithmetic
p1 = 0x4006e4
j = 2
&j["Programming"] = 0x4006e6
p1 + j = 0x4006e6
Print strings
&j["Programming"] = ogramming
p1 + j = ogramming

Printing value of a pointer to a pointer

I am trying to wrap my head around "pointer to a pointer". And I tried some experiments and I got stuck here for a while:
int array[5] = {4 , 5 ,6 ,7 ,8};
int *p = array;
int **pp = &p;
for ( int i = 0; i < 4; i ++)
{
printf("\nprinting\n");
printf("Source: %d\n", array[i]);
printf("Output by pointer: %d, %d\n", p[i], *(p + i));
printf("Output by pointer to a pointer: %d, %d\n", *pp[i], **(pp + i) );
}
And I got this as output:
printing
Source: 4
Output by pointer: 4, 4
Output by pointer to a pointer: 4, 4
printing
Source: 5
Output by pointer: 5, 5
I don't understand why after 1 loop, the program stop at the 2nd loop- line 9. Did I misunderstand anything basic knowledge or something else.
Thank you for reading.
Change the last printf to:
printf("Output by pointer to a pointer: %d, %d\n", (*pp)[i], *(*pp + i) );
You're basically using *pp in place of p, but the * operator doesn't group as tightly as [] so you need to use parentheses in the first form. In the second form, you need to dereference pp before adding i, after which the result is dereferenced.
For starters it is unclear why there is used the magic number 4 in the loop instead of the number 5 that is the number of elements in the array
for ( int i = 0; i < 4; i ++)
^^^^^
The pointer pp does not point to first element of an array. It points to a single object
int **pp = &p;
So these expressions
*pp[i] (that is equivalent to *(pp[i] )
and
**(pp + i)
does not make sense.
An expression using the pointer p can be written using the pointer pp like *pp.
So these correct expressions
p[i]
and
*(p + i)
can be written using the pointer pp the following way (just substitute p for *pp taking into account operation precedences)
( *pp )[i]
and
*( *pp + i )
You acesses to pointer thru pointer-to-pointers are wrong:
you must access the pointee as the array:
int array[5] = {4 , 5 ,6 ,7 ,8};
int *p = array;
int **pp = &p;
for ( int i = 0; i < 4; i ++)
{
printf("\nprinting\n");
printf("Source: %d\n", array[i]);
printf("Output by pointer: %d, %d\n", p[i], *(p + i));
printf("Output by pointer to a pointer: %d, %d\n", (*pp)[i], *(*pp + i) );
}
This line is wrong
printf("Output by pointer to a pointer: %d, %d\n", *pp[i], **(pp + i) );
You need to change it to
printf("Output by pointer to a pointer: %d, %d\n", (*pp)[i], *(*pp + i) );
so that you dereference the double pointer before using it as a normal pointer.
You can think of it like this:
p is the same as (*pp)
In other words - in a valid expression that uses p you are allowed to substitute p with (*pp). That is
p[i] --> (*p)[i]
*(p + i) --> *((*pp) + i) --> *(*pp + i)
Notice that the parenthesis is important. The parenthesis can be removed in the second example but not in the first as [] has higher precedence than *.
Doing pp + i generates a pointer that doesn't point to any valid object. So when you dereference it using **(pp + i) you do an illegal access an your program crashes.

Printing address of a C array

The below question may sound repetitive to the community but sometimes you need to ask the exact question in your mind to understand things correctly. I am trying to get a thorough understanding of pointers. I was watching a video when the presenter says print the address of each element of array by using &pointername[subscript]. My question is why not just pointer. In the below code after doing j++ wont J have address of the array elements? why should I use &j[k]? what is the difference between &j[k],j(if there is)
#include <stdio.h>
void main()
{
int i[] = {1, 2, 3, 4, 5}, *j, k;
j = i;
for (k = 0; k < 5; k++)
{
printf("%p, %p, %p\n", &j[k], j, i);
j++;
}
}
Thanks,
Sahana
In most cases when you refer to an array in C, what you automatically get is a pointer to the array's first element. In other words, when you wrote
j = i;
it was exactly as if you had written
j = &i[0];
And this further means that when you write
i[k]
it is exactly equivalent to
*(i + k)
This then means that
&i[k]
will always be equal to
i + k /* or &i[0] + k */
And in your program it's also true that j[k] is equal to *(j + k), meaning that &j[k] is equal to j + k.
It looks like your program is trying to demonstrate these equivalences, but it's confusing because you're both incrementing j and indexing j by k. Here's a version of your program that should make it more clear what's going on. (Among other things, I've changed the array's name to a, because "i" is a very confusing name for an array! Similarly, I've changed j to p.)
int main()
{
int a[] = {11, 22, 33, 44, 55}, *p, k;
printf("a = %p\n", a);
p = a;
for(k=0; k<5; k++)
{
printf("%d %p %p %d %d\n", k, &a[k], p, a[k], *p);
p++;
}
}
You are partially right:
With the assignment j=i, j points to the first element in the array i. From now on j[k] will point to the same memory location as i[k].
With j[k] you are retrieving the data of the k-th cell in the array. So j[k] is an int.
If you want to get the address of it you have to place a & in front of it.
In C, &ptr[index] is exactly the same as ptr+index or even &index[ptr]
and arrays are decayed into pointers, in particular when passing them as arguments (e.g. to printf).
Read exactly what decaying an array means in your favorite C programming book. Notice that sizeof, when applied to an array or to a pointer, is not the same. So with int arr[5]; on my Linux/x86-64 desktop: when passing arr as an argument, it is decayed to a pointer so is the same as &arr or &arr[0]; but sizeof(arr) is 20 but sizeof(&arr) is 8 (like sizeof(ptr) after some int*ptr = &arr[3];)and sizeof(arr[0])is 4.
Simply
#include <stdio.h>
int main() {
int i[] = { 1, 2, 3, 4, 5 }, j;
for (j = 0; j < 5; ++j)
printf("%p\n", &i[j]);
return 0;
}
Output
0xbff22d8c
0xbff22d90
0xbff22d94
0xbff22d98
0xbff22d9c

Printing pointer value with increment of the address in C

#include <stdio.h>
#include <stdlib.h>
int main()
{
int k,*ptr=NULL;
int arr[]={1,2,3,4,5,6,7,8,9,10};
ptr=arr;
printf("%d ",*ptr++);
printf("%d ",*(ptr++));
printf("%d ",(*ptr)++);
printf("%d ",*++ptr);
printf("%d ",++*ptr);
}
Why does the second printf print the number 2 ? It should print 3.
As everyone else said, the distinction is between pre-incrementing (where the increment occurs before the value is fetched) and post-incrementing (where the value is fetched and then the increment occurs). The value 2 should be printed, of course.
Maybe this assertion-laden code will help. The assert() macro stops the program if the condition specified is false when it is executed. The assertions do not fire.
The assertions show how the value of ptr changes, and also how the values in the array change.
#include <assert.h>
#include <stdio.h>
int main(void)
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int *ptr = arr;
assert(ptr == &arr[0]);
printf("%d\n",*ptr++); // print 1; ptr = &arr[1]
assert(ptr == &arr[1]);
printf("%d\n",*(ptr++)); // print 2; ptr = &arr[2]
assert(ptr == &arr[2]);
assert(*ptr == 3);
printf("%d\n",(*ptr)++); // print 3; ptr = &arr[2]; arr[2] = 4
assert(ptr == &arr[2]);
assert(*ptr == 4);
printf("%d\n",*++ptr); // print 4; ptr = &arr[3]
assert(ptr == &arr[3]);
assert(*ptr == 4);
printf("%d\n",++*ptr); // print 5; ptr = &arr[3]; arr[3] = 5
assert(ptr == &arr[3]);
assert(*ptr == 5);
printf("Offset: %d\n", (int)(ptr - arr));
for (int i = 0; i < 9; i++)
printf("a[%d] = %d\n", i, arr[i]);
return 0;
}
Output:
1
2
3
4
5
Offset: 3
a[0] = 1
a[1] = 2
a[2] = 4
a[3] = 5
a[4] = 5
a[5] = 6
a[6] = 7
a[7] = 8
a[8] = 9
post increment operator increments the variabl after accessing the value.
So, after getting *ptr, which is 2, ptr increases itself.
Not, because ptr++ return the value BEFORE the incrementation, so the value is 2.
*ptr++ first dereferences the pointer which gives 2, then increments the pointer
The expression *(ptr++) is a post increment expression so the value of of that expression is ptr and then it is incremented. So the result of the expression is that it still points to the 2
the * operator applies to the result of p++, which is the value of original p (prior to the increment). So it prints 2. I you want 3 to be printed you should do (++p) which returns the incremented value.
It should print 2, because the postfix operator ++ first returns the value and then increments it.
The fact that you added brackets around it (*(ptr++)) does not influence the increment.
The value will be incremented after the whole line.
Looking at disassembly might help you to see what happens at that line.
The *ptr++ returns the value at ptr and then increments it,so in the second printf() statement it only returns 2 and then increments it to 3.

Resources