Adding integer to pointer - c

So, I was messing around with pointers in C
int o = 10;
int x = 20;
int *pA = NULL;
pA = &o;
and after adding an integer to the
pointer
pA += x;
the address stored in the pointer changed from
000000000061FE18
to
000000000061FE68
After checking the value the address was pointing to using *pA the value was 0 and I could add an integer to this address using
*pA += x;
and *pA became equal to 20, but the value stored in variable o was still 10.
Could anyone explain what happened here?

pA += x; - The pointer pA itself is incremented by the value of x multiplied by the size of type pA is pointing to and is equal to the size of x, which is int.
So, assume sizeof(int) or sizeof(x) is 4 and x has the value of 20, you end up multiplying the pointer value of pA by 80 because 4 * 20 = 80, which is matching to your test results.
0x61FE68 - 0x61FE18 = 0x50 = 80d.
After adding an integer to the pointer
pA += x; .... (and) checking the value the address was pointing to using *pA the value was 0...
Since you incremented the pointer pA itself by 20 * sizeof(int) with pA += x;, pA points no longer to any valid object and beyond the bounds of the object it should point to.
To increment the pointer in this way invokes undefined behavior as well as dereferencing this pointer.
That it displayed 0 is just happen arbitrary to the situation. You can't rely on anything. The value can change already at the next execution.
... and I could add an integer to this address using *pA += x; and *pA became equal to 20.
The behavior is undefined as said above. pA does not point to any legally referenced object.
...but the value stored in variable o was still 30.
o isn't changed at all. With the first statement pA += x; you incremented the pointer itself, not the object o pA pointed to at the first place.
Could anyone explain what happened here?
You incremented the pointer pA by sizeof(int) * 20 with the first pA += x;. Everything else can't be really explained, because the behavior is just undefined.

Here you have a small program which should explain pointer arithmetic a bit.
#include <stdio.h>
#define PRINTDIFF(type, p1, p2) printf("sizeof(%s) = %zu p1=%p p2 = %p diff(bytes) = %zi \ndiff(objects) = %zi diff(bytes)/sizeof(%s) = %zi\n\n", \
#type, sizeof(type), \
(void *)(p1), \
(void*)(p2), \
((char *)(p2) - (char *)(p1)), \
(p2) - (p1),\
#type, \
((char *)(p2) - (char *)(p1)) / sizeof(type))
int main(void)
{
short s;
char c;
int i;
long long ll;
long double ld;
short *sp = &s;
char *cp = &c;
int *ip = &i;
long long *llp = &ll;
long double *ldp = &ld;
PRINTDIFF(short, sp, sp + 10);
PRINTDIFF(char, cp, cp + 500);
PRINTDIFF(int, ip, ip + 5);
PRINTDIFF(long long, llp, llp + 5);
PRINTDIFF(long double, ldp, ldp + 5);
}
https://godbolt.org/z/4eP3rc
And the result:
sizeof(short) = 2 p1=0x7ffe0660eb76 p2 = 0x7ffe0660eb8a diff(bytes) = 20
diff(objects) = 10 diff(bytes)/sizeof(short) = 10
sizeof(char) = 1 p1=0x7ffe0660eb75 p2 = 0x7ffe0660ed69 diff(bytes) = 500
diff(objects) = 500 diff(bytes)/sizeof(char) = 500
sizeof(int) = 4 p1=0x7ffe0660eb70 p2 = 0x7ffe0660eb84 diff(bytes) = 20
diff(objects) = 5 diff(bytes)/sizeof(int) = 5
sizeof(long long) = 8 p1=0x7ffe0660eb68 p2 = 0x7ffe0660eb90 diff(bytes) = 40
diff(objects) = 5 diff(bytes)/sizeof(long long) = 5
sizeof(long double) = 16 p1=0x7ffe0660eb50 p2 = 0x7ffe0660eba0 diff(bytes) = 80
diff(objects) = 5 diff(bytes)/sizeof(long double) = 5
BTW when you learn you should experiment yourself writing the short programs which will help you understand the C language. There is no easy, effortless way of learning C

The new address pointed by a pointer, after a constant value is added to it, depends on the type it points to:
NewAddress = OldAddress + ConstantValue * sizeof ( Type )
So, in plain math, with pA += x, you have
new_address_pointed_by_pA = old_address_pointed_by_pA + x * sizeof( int )
And since x=20 and an integer in your machine is 4 bytes big, this becomes
new_address_pointed_by_pA = old_address_pointed_by_pA + 20*4 =
= old_address_pointed_by_pA + 80
That's exactly what you experience, as 0x61FE68 - 0x61FE58 = 0x50. Your addresses, in fact, are represented in hexadecimal format. So the new address is 0x50=80 beyond the old one, and that fits with the simple calculation I showed above.
What does that new address contain? Well, we don't know. It depends on the history of that specific memory location.
If it was never used, it's not surprising it contained 0. And it was also expected that after *pA = x it contained 20. And, again, it is not surprising at all that the location it was originally pointing remains unchanged.
But... with that assignment you could have raised a segmentation fault exception. An OS usually raises this signal when a memory location not assigned to your task is accessed.
So, pay attention when you play with pointers, making sure that any arithmetics performed on them leads to legal new values.

Related

What does *--a = *--b mean in C

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.

Pointer difference between int *val = otherVal and int val = otherVal

I am little confused and tried finding explanation but all "difference" questions asked are about type *name vs type* name which i know answer of.
I have code like this:
int a = 1;
printf("a = %d", a); // Prints 1
int *pt = a;
printf("pt = %d", pt); // Prints 1
*pt = 2; // Crash why? What am i pointing to here?
&pt = 2; // Not even compiling since
pt = 2; // Works
printf("pt = %d\n", pt); // Prints 2
printf("a = %d\n", a); // Prints 1
I know in order to change value of a i should have done int *pt = &a and then *pt = 2 and that is not my question.
My question is in this case, is using int *pt = a same as using int pt = a or is there any advantage of using it as pointer?
int a = 1;
...
int *pt = a;
Attempts to store the value 1 as the address held by pointer pt. Any dereference of pt is guaranteed to SegFault as address 1 is well down at the bottom of the system-reserved memory range -- which you have no ability to access, resulting in an access violation and SegFault.
What Is A Pointer?
A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int a = 5;, a pointer would simply hold the address where 5 is stored in memory, e.g. int *b = &a;. It works the same way regardless what type of object the pointer points to. It is able to work that way because the type of the pointer controls the pointer arithmetic, e.g. with a char * pointer, pointer+1 point to the next byte, for an int * pointer (normal 4-byte integer), pointer+1 will point to the next int at an offset 4-bytes after pointer. (so a pointer, is just a pointer.... where arithmetic is automatically handled by the type)
So in your case:
int a = 1;
...
int *pt = &a;
Will assign the address where a is stored in memory to the pointer variable pt. You may then access the value at that address by dereferencing pt (e.g. *pt)
What you are doing is setting the address to which the pointer pt points to, to what a is currently holding (1 in your case). Since *a is most definitely not a valid and accessible address you will most likely get a segmentation fault when trying to dereference it. This is somewhat the same as if you are creating a null pointer by int *pt = 0 but instead of 0 you use whatever is in a.
Keep in mind that there is probably something funky going on with converting a signed int to an address which only makes the whole thing even worse.

what does *p contain?

As per multiple sources, a pointer p points to a value when it is dereferenced. Thus, we may say that a pointer contains an address as it's value, and when the dereference operator (*) is used, the value at the address is returned.
A pointer may be assigned a value as follows:
int a = 90;
int *p = &a;
if we assign a pointer it's value as follows:
int *p;
*p = 60;
60 is alloted to p and causes undefined behavior upon dereferencing since 60 is not a valid address. (As per the answer to this question).
However, for the following code:
int a = 90;
int *p = &a;
printf ("p is %d \n",*p);
printf ("a is %d \n", a);
printf ("address is %p \n",p);
*p = 100;
printf ("p is %d \n",*p);
printf ("a is %d \n", a);
printf ("address is %p \n",p);
The following output is recieved :
p is 90
a is 90
address is 0028FED8
p is 100
a is 100
address is 0028FED8
ie, the expression *p = 100 changes the value at a, and not the value contained by p.
HOW ??????
*p = &a doesn't even compile. p is a pointer to int. It currently has an undefined value, therefore assigning anything to *p is undefined behaviour and would most likely crash. However, even if p did point to an int, you could only assign an int to *p, &a is a pointer to int, not an int, so this doesn't compile.
In your second example, *p = 60, the value of p is undefined, so you are trying to store 60 to an undefined location in memory. Instant crash. p isn't modified by this, so your explanation is wrong. p is not set to 60. You can't set p to an int. You can only set it to a pointer to int.
Correct:
p = &a;
*p = 60;
the code you wrote at the begining:
int *p;
int a = 90;
*p = &a;
is not valid, The asterisk (*) in line 1 indicate that it is a pointer, it is not the dereference operator as in line 3.
the following code:
int a = 90;
int *p = &a;
is equivalent to:
int a = 90;
int *p;
p = &a;
(p) is a pointer , and now is pointing at address of (a)
*p = 100;
so, you just assign a value to a, a = 100 .
and you are printing the same value from the same address.
You had asked:
ie, the expression *p = 100 changes the value at a, and not the value contained by p.
You can read the comment section for explanation of each line of C code and I'm not using exact address locations but using arbitrary ones for demonstration purposes:
int *p; // Stack variable pointer to integer type w/ p's address being 4 bytes # 0x00000000
int a = 90; // Stack integer variable `a` and initializing it to the value of 90 located # 0x00000040
*p = &a; // Dereferencing the pointer `p` to be equal to the address of `a` ... One would think
// that the address value of `a` 0x00000040 in hex would be stored into `a` which
// has the value of 64 in decimal, however this is not always the case and this should be
// undefined behavior, but can still compile and run depending on the compiler and architecture.
// It may run or crash or not even compile or build at all. Most compilers should throw an error.
*p = 100; // 'p' is located at 0x00000000 and contains the value 0x00000040 and by dereferencing it
// it will assign the value of 100 to the stack address location of 0x00000040. Thus this
// changes the value of `a` to 100
// These two statements are in a sense equivalent
*p = 100; a = 100;
// If one was to assign the address of `a` to `p` as such:
p = &a;
EDIT
// Therefor the statement `*p=100` will only work if the statement
// `p=&a` is defined and evaluated beforehand.
EDIT
Now as for the question based on the Title: "what does *p contain?" with the op's original code provided *p actually contains garbage or what ever was assigned to it upon declaration.
As per multiple sources, a pointer p points to a value when it is dereferenced.
Not quite. A pointer points to an object. Dereferecing a pointer produces that object. Using an object in a context where a value is needed produces the stored value.
int *p = &a;
The object that p now points to is a.
*p = 100;
Dereferencing p produces the pointed-to object, namely a. Since this is not a context where the stored value is needed, a's value isn't read, it remains the object a which is assigned the value 100.
Or, simply put, *p means a, therefore *p = 100 means a = 100.

Incrementing Pointers

Consider this program:
#include <stdio.h>
int main()
{
double *dp;
double **dpp;
dpp=&dp;
dp++;
dpp++;
return 0;
}
Suppose dp has address 100 and dpp has address 1000.
What will the address of these pointers be after incrementing?
The simplest thing is to make your program compilable and give it strictly defined behaviour, then run it.
#include <stdio.h>
int main(void)
{
double d[2] = { 3.141593, 2.718128 };
double *dp = &d[0];
double *dpa[2] = { &d[0], &d[1] };
double **dpp = dpa;
printf("dp = %p\n", (void *)dp);
printf("dpp = %p\n", (void *)dpp);
dp++;
dpp++;
printf("dp = %p\n", (void *)dp);
printf("dpp = %p\n", (void *)dpp);
return 0;
}
Note how the code carefully ensures that the pointers always point to valid data. You could extend the printing to print *dpp (another pointer) and **dpp and *dp (both double values).
On my machine (Mac OS X 10.9.1, GCC 4.8.2, 64-bit compilation), the output is:
dp = 0x7fff56945510
dpp = 0x7fff56945520
dp = 0x7fff56945518
dpp = 0x7fff56945528
When compiled for 32-bit, the output is:
dp = 0xbfffc600
dpp = 0xbfffc5f0
dp = 0xbfffc608
dpp = 0xbfffc5f4
The jump of 8 in dp is a consequence of sizeof(double) == 8 (for both 32-bit and 64-bit compilations). The change in dpp of 4 for the 32-bit compilation and 8 for the 64-bit compilation is a consequence of sizeof(double *) == 4 for 32-bit and sizeof(double *) == 8 for 64-bit.
dp++ is undefined behavior, since dp was never initialized. There are no guarantees about what will happen.
What will probably happen, though relying on this would be a poor decision, is that the numerical value in memory of dp is incremented by sizeof(double), and the numerical value of dpp is incremented by sizeof(double *). sizeof(double) is probably 8, and sizeof(double *) is probably 4 or 8.
double *dp => is pointer to variable of type double (size of dp is 4 bytes only)
double **dp1 => is a pointer to pointer which is pointing to double (size of dp1 is 4 bytes)
Pointer's size is always 4 bytes (assuming 32-bit machine; on a 64-bit machine, it's 8 bytes)
i.e pointer size depends on how big the memory address is.
When you increment dp++, you increment pointer pointing to double whose size is 8 bytes so it increments by 8 bytes (100 => 108).
When you increment the pointer to pointer, its size is 4 bytes so it increments by 4 bytes only (1000 => 1004)
Pointer increments depend on the type of object it is pointing at.
In your code you haven't declared a variable of type double directly; you have initialized **dp1 which will will result in undefined behavior.
double a = 10.00;
dp = &a;
add the above two line to understand your code better (just one of the way).

How the output of this program comes out to be this?

I have a piece of code written in C where some pointer arithmetic is performed. I would like to know how the output comes to be this?
#include <stdio.h>
int main()
{
char arr[] = "gookmforgookm";
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;
}
Output is below:
ptr2 - ptr1 = 3
(int*)ptr2 - (int*) ptr1 = 0
Strictly speaking, you're invoking undefined behaviour and any result that the program produces is OK according to the C standard.
However, you're probably on a machine where sizeof(int) == 4 (as opposed to say, 2). Since there are 4 bytes to an integer, two addresses which are 3 bytes apart are part of the same integer, so the difference between the addresses is 0 * sizeof(int). You might find a different answer if you chose ptr1 = arr + 1;, or you might not. But that's the beauty of undefined behaviour - it would be 'right' either way.
After the subtraction you need to divide the result in the size of the pointed type.
(int*)ptr2 - (int*)ptr1 == (0x1000003 - 0x1000000) / sizeof(int)
(int*)ptr2 - (int*)ptr1 == (0x1000003 - 0x1000000) / 4 == 0
ptr1 and ptr2 are both char * type, that means one byte one pointer.
char *ptr2 = ptr1 + 3;
so
ptr2 - ptr1 = 3
Next, you cast both pointer to type int *, int type need 4 byte, so both pointer aim at the same int, both pointer have the same value through the memory align, you get the 0 result.
When you subtract two pointers, as long as they point into the same array, the result is the number of elements separating them.
Pointer Subtraction and Comparison
The memory addresses of the elements of the same array are always sequential. i.e
if the memory adress of myarray[0] is:
0x4000000
then the memory address of myarray[2] will definitely be
0x4000002
So when you store the address of arr into ptr1 assume it to be x
, and then when you make the address of ptr2, three units higher than ptr1, it will be x+3. So when you subtract ptr1 from ptr2 the answer will be:
(x+3) - x = 3
Hence the answer.
In the second printf() statement, if you want it to display the same result as above (3), you have to convert the pointer to int and not int*.
char *myvar; // given contents somewhere
int addr = (int)myvar; // addr now = the char pointer
So In your case:
printf ("(int)ptr2 - (int) ptr1 = %d", (int)ptr2 - (int)ptr1);

Resources