Pointer Subtraction in C with an array - c

If I have the following lines of code, why is b-a = 2?
int a[] = {1,2,3,4,5};
int *b = &(a[2]);

To elaborate slightly on Eugene's answer, a is a pointer to the beginning of the array, and a[2] is the same as *(a+2).
So you could say that the & "cancels" the * as you dereference the pointer and then look at the address of the element that it points to. So *b = &(a[2]) = &(*(a+2)) = a+2.
Therefore b-a=2

Related

About Pointers and arrays and types and casting

Say I have the following problem:
main(void) {
int * p;
int nums [3] = {1,5,9};
char c [3] = {'s','t','u'};
p = nums [2];
*p = (int) *c;
}
What does the last line mean?
Let's break it down: *p = (int) *c;
c is a char array.
*c is the first element of the char array, because c[0] = *(c+0) = *(c) = *c
(int) *c casts the first element of the char array c to an integer. This is required, because with...
*p = (int) *c you assign the to an integer casted char to the content of pointer p.
This code will not work, or will cause problems if it does.
the line;
p = nums[2];
sets the value of the pointer p to the value 9. This is not likely a legal value for your pointer. If it were, then the memory location 9 would be set to 115 which is the integer value of 's'.
*c → Decay c to pointer-to-first-element, and access the pointed-to value. Same as c[0].
(int) *c → cast that value to int.
*p = (int) *c → assign that to what p points to.
There are many issues in this code, let's address them first.
Firstly, main(void) is not conforming code. You need to change that to int main(void).
Secondly, p = nums [2]; is wrong. p is of type int *, and nums[2] is of type int. You may not assign an int to a int * and expect something fruitful to happen. Maybe what you meant to write is p = &nums[2];. Without this modification, going further will invoke undefined behavior as you will try to access a memory location that is invalid to your program.
Then, coming to your question,
*p = (int) *c;
it basically dereference cNOTE to get the value, then cast it to an int type and store into the memory location pointed by p. However, in C, this casting is not required. The above statement is equivalent to
*p = *c;
anyway.
NOTE: Array name decays to the pointer to the first element of the array, i.e., in this code, using c is the same as &c[0], roughly.

Pointers to arrays

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/

What is the difference between p = *a[0] and p=&a[0]

#define N 20
int a[2N], i, *p, sum;
p = a;
/* p=a is equivalent to p = *a[0];
• p is assigned 300.
• Pointer arithmetic provides an alternative to array indexing.
• p=a; is equivalent to p=&a[=]; (p is assigned 300)
Here I am not getting how p=*a[0] and p=&a[0] are same? *a[0] references the element at the memory address.
Point 1
Do your understand, here int a[2N] is invalid code?
This 2N does not mean 2*N, rather this N is considered as a suffix (to integer literal 2) which is invalid.
Thanks to Mr # Lưu Vĩnh Phúc for the comment below.
If you wanted something like int a[40], write int a [2*N]
Point 2
p=*a[0] and p=&a[0] are same
No, they're not same. Actually, with the current code snippet, *a[0] is invalid.
FWIW, p = a; and p = &a[0]; are same, because the array name represents the base address, i.e., the address of the first element in the array.
p = a and p = &a[0] are indeed equivalent. In this case, you assign the address of the first element in the array to p (because the name of the array = pointer to its first element). p=*a[0] and p=&a[0] are not the same; *a[0] requires that a be an array of pointers, and dereferences its first member.
The meaning of p = &a[0] is as follows
For example :
int a[4];
a[0] a[1] a[2] a[3]
a --------> [ ][ ][ ][ ]
Equivalents
// Reference
&a[0] = a;
&a[1] = a+1;
...
&a[3] = a+3;
// Value
a[0] = *a
a[1] = *(a+1)
..
a[3] = *(a+3)
In arrays of C programming, name of the array always points to the first element of an array. Here, address of first element of an array is &a[0]. Also, a represents the address of the pointer where it is pointing i.e., base address . Hence, &a[0] is equivalent to a, so p = a or p = &a[0] both are same.

Strange output with pointer arithmetic

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;

Array Assignments in C Using Pointer Arithmetic

How can I change the value in an array when I access a particular element using pointer arithmetic?
#include <stdio.h>
int main() {
int a[3] = {1, 1, 1}, b[3] = {2, 2, 2};
a++ = b++; // How can I get this to work so a[1] = b[1]?
return 0;
}
Arrays are not pointers. Repeat this three times; arrays are not pointers.
You cannot increment an array, it is not an assignable value (i.e., you cannot mutate it). You can of course index into it to get a value back:
a[1] = b[1];
Secondly, your current code is attempting to increment and then assign a new value to the array itself, when you meant to assign to an element of the array. Arrays degrade to pointers when required, so this works too:
int *a_ptr = a;
int *b_ptr = b;
*++a_ptr = *++b_ptr;
// or, better...
a_ptr[1] = b_ptr[1];
Which is what you meant to do. I prefer version 1 and, more often than not, use indexing with pointers as well because it is often easier to read.
How can I get this to work so a[1] = b[1]?
Simple:
a[1]++;
if you just wanted to increment a[1] (1) to be what b[1] happens to be (2), or
a[1] = b[1];
if you want a[1] to have the same value as b[1] regardless of what that value is.
when I access a particular element using pointer arithmetic?
In your example, you are not accessing any element, nor are you doing pointer arithmetic because a and b are arrays, not pointers. The formulation of your question is difficult to interpret, both because of that and because
a++ = b++;
1) is completely meaningless 2) would not be legal C even if a and b were pointers, because the left side must be an lvalue, but a++ is not 3) is not discernably related to your wish for a[1] to be the same as b[1]. Possibly what you want is:
int* ap = a; // get pointer to first element of a
int* bp = b; // get pointer to first element of b
// point ap to second element of a and
// point bp to second element of b and
// copy the value at *bp to *ap
*++ap = *++bp;
That would indeed set a[1] to b[1].
Your arrays in this case are not actually pointers. They are converted by the compiler when they are accessed as pointers, but I don't believe that you're allowed to do something like a++.
If you want to do this with arithmetic, you'll need actual pointers:
int *ap = a, *bp = b;
*ap++ = *bp++;
That is like doing a[0] = b[0]; and then moving each pointer to the next element in their associated array.
But your question says you want to set a[1] = b[1]. Well, you could do this:
*++ap = *++bp;
Or you could just use the array indices and make it much more obvious what you're doing.

Resources