the size of distance between two pointers - c

void main() {
int a = 2;
int *p = &a;
int *q = p++;
printf("%d %d\n", p, q);
int b = p - q;
printf("%d", b);
}
Why does it print 1? I've tried with other pointers but didn't succeed. I thought it would print the size of int because the distance between them is 1 * sizeof(int) but it prints 1.

why it prints 1?
Because C specifies pointer subtraction as the difference in the indexes (subscript) of the array, not the difference in address values.
1 past the object is like the an array element after the int a;
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type. C17dr § 6.5.6 7
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. § 6.5.6 8
Subscript 1 - subcript 0 --> 1.
The result is 1 even if int a was char a or long double a.

For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
To output pointers you have to write
printf("%p %p\n", ( void * )p, ( void * )q);
In the initializer of the pointer q
int* q = p++;
there is used an expression with the postfix increment operator. Its value is the value of the operand before incrementing.
So the pointer q is initialized by the address of the variable a and as a side effect the pointer p is incremented and points to the memory after the object a. That is between the addresses (in the extent of memory bounded by these addresses) stored in the pointers p and q there is stored only one object a. So according to the pointer arithmetic the result of the expression p - q is 1.
On the other hand, the difference between the addresses stored in the pointers p and q is equal to the value of sizeof( int ) that is to the value of sizeof( a ).
If you will write for example
int b = ( char * )p - ( char * )q;
then the value of b will be equal to sizeof( a ) because in this case the memory occupied by the variable a is interpreted as a character array and sizeof( char ) is always equal to 1.

There are a few errors in this code:
The return type of main() should be int instead of void.
The printf() statement has two integer format specifiers, but the arguments passed are pointers, which are not guaranteed to have the same size as integers. Therefore, using the %d format specifier to print pointers is not correct. You can use the %p format specifier to print pointers.
The variables p and q are pointers to int, so the difference between them (i.e., p - q) should be divided by the size of int to get the number of elements between them.
Here is the corrected code:
#include <stdio.h>
int main() {
int a = 2;
int* p = &a;
int* q = p++;
printf("%p %p\n", p, q);
int b = (p - q) / sizeof(int);
printf("%d", b);
return 0;
}
This code will print the memory addresses of p and q, followed by the difference between them in terms of the number of int elements.

Related

Double Pointer to Array in C

Below is a code snippet and the outputs:
int main()
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = A;
printf("*p is : %d\n", *p);
//Output : *p is : -547221600
printf("*q is : %d", *q);//Why ?
//Output : *q is : 1100
}
p is a pointer to integer array of size 3. *p + i points to ith array in A i.e. A[i].
What would happen if instead I use double pointers (q in the above code).
I am unable to understand that why *q gives 1100 as the value.
For starters this assignment
q = A;
is incorrect because the left operand (having the type int ( ** )[3]) and the right operand (having the type int ( * )[3] after the implicit conversion of the array designator to a pointer to its first element) have different types and there is no implicit conversion between the types.
The compiler can issue an error like this
error: assignment to ‘int (**)[3]’ from incompatible pointer type ‘int (*)[3]’
You could write instead
q = &p;
In this call of printf
printf("*p is : %d\n", *p);
there is used an incorrect argument. The type of the expression *p is int[3]. So in fact you are trying to output a pointer (due to implicit conversion of the array designator to a pointer to its first element) using the conversion specifier %d that is designed to output integers.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = &p;
printf( "A is : %p\n", ( void * )A );
printf( "*p is : %p\n", ( void * )*p );
printf( "*q is : %p\n", ( void * )*q);
return 0;
}
Its output might look like
A is : 0x7ffdb1c214e0
*p is : 0x7ffdb1c214e0
*q is : 0x7ffdb1c214e0
That is the first call of printf output the initial address of the first element A[0] (of the type int[3]) of the two-dimensional array.
The second call of printf outputs the address of the first element of the first "row" of the two-dimensional array that is &A[0][0].
The third call of printf outputs the value stored in the pointer p that is the address of the first "row" of the two-dimensional array A.
If you want to output the first elements of the array A using the pointers then the program can look the following way.
#include <stdio.h>
int main(void)
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = &p;
printf( "**p is : %d\n", **p );
printf( "***q is : %d\n", ***q);
return 0;
}
Now the program output is
**p is : 1100
***q is : 1100
p is a pointer to integer array of size 3.
Correct.
*p + i points to ith array in A i.e. A[i].
Incorrect. p + i would be a pointer to an array.
When you indirect through the pointer to array, the result is an array, and when you add an integer to an array, the array decays to pointer to element of that array and since *p is an array of integers, the decayed pointer points to an integer element of the array. Thus, the result of *p + i is a pointer to an integer (i'th sibling of the first element of the first array).
What would happen if instead I use double pointers (q in the above code).
I assume that by substituted above code, you mean *q + i.
If you have a pointer to a pointer to an array, then indirecting through the pointer results in a pointer to an array. Adding an integer to pointer to an array gives you pointer to an array that is a sibling.
q = A;
This assignment is ill-formed in C++. An array of arrays of integers is not convertible to a pointer to pointer to an array.
printf("*p is : %d\n", *p);
printf("*q is : %d", *q);//Why ?
%d is an invalid format specifier for int* as well as for a int (*)[3]. By using invalid format specifier, the behaviour of this program is undefined. That explains all of the behaviour.

Having difficulty in understanding of pointer to pointer increment value

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.

CLion vs TutorialsPoint C Compiler returning different values [duplicate]

#include<stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50, 60};
int *ptr1 = arr;
int *ptr2 = arr + 5;
printf("Number of elements between two pointer are: %d.",
(ptr2 - ptr1));
printf("Number of bytes between two pointers are: %d",
(char*)ptr2 - (char*) ptr1);
return 0;
}
For the first printf() statement the output will be 5 according to Pointer subtraction confusion
What about the second printf() statement, what will be the output?
To quote C11, chapter §6.5.6, Additive operators
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements.
So, when you're doing
printf("Number of elements between two pointer are: %d.",
(ptr2 - ptr1));
both ptr1 and ptr2 are pointers to int, hence they are giving the difference in subscript, 5. In other words, the difference of the address is counted in reference to the sizeof(<type>).
OTOH,
printf("Number of bytes between two pointers are: %d",
(char*)ptr2 - (char*) ptr1);
both ptr1 and ptr2 are casted to a pointer to char, which has a size of 1 byte. The calculation takes place accordingly. Result: 20.
FWIW, please note, the subtraction of two pointers produces the result as type of ptrdiff_t and you should be using %td format specifier to print the result.
If you have two pointers of type T that point to elements of the same array then the difference of the pointers yields the number of elements of type T between these pointers
So the first output statement
printf("Number of elements between two pointer are: %d.",
(ptr2 - ptr1));
outputs 5 - the number of elements of type int between pointers ptr1 and ptr2.
It is the so-called pointer arithmetic.
Pointers (char*)ptr1 and (char*)ptr2 have the same values as the original pointers ptr1 and ptr2 but they consider (reinterpret) the memory extent as an array of type char each element of which has size equal to sizeof( char ). In C sizeof( char ) is always equal to 1.
Thus the difference ( char * )ptr2 - ( char * ) ptr1 gives the number of elements of type char that can fit the memory extent. It is evident that
sizeof( char ) is not greater than sizeof( int ). So the same memory extent can accomodate more elements of type char than of type int. If for example sizeof( int ) is equal to 4 then the memory extent can accomodate 5 * sizeof( int ) elements of type char that is 20.
Pointer arithmetics is always in the units of the base type.
In your case you have
int *ptr1 = ...
Then doing ptr1 + 5 will add sizeof(*ptr1) * 5 bytes to the pointer ptr1. Considering that sizeof(*ptr1) (which is the same as sizeof(int)) is 4, then you get 4 * 5 which equals 20 bytes.
Each array element is an int and there are 5 elements between both the pointers. Thus there will be 5*sizeof(int) amount of bytes in between both the pointers.

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;

C assigning the address of a 2D array to a pointer

I was reading through some lecture notes that in order for a pointer to reference a 2D array, it has to be given the address of the first element.
int a[10][10];
int *p = &a[0][0];
I've never tried this, so I was curious why isn't it enough to assign the array itself to the pointer, just as we do in a 1D case.
int a[10][10];
int *p = a;
The array is kept in an uninterrupted 'line' of memory anyway, and 2D arrays only have a different type, but the same structure as 1D arrays.
By doing this
int *p = &a[0][0];
I don't see how we give the pointer any more information than by doing this
int *p = a;
Or maybe all arrays regardless of their number of dimensions have the same type, the only difference being that multidimensional arrays store their extra dimensions before their first element and we need to jump over those memory spaces which remember sizes of an array's dimensions?
First, some background:
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
Given the declaration
int a[10][10];
the expression a has type "10-element array of 10-element array of int". Unless this expression is the operand of the sizeof or unary & operators, it will be converted to an expression of type "pointer to 10-element array of int", or int (*)[10].
Given that declaration, all of the following are true:
Expression Type Decays to
---------- ---- ---------
a int [10][10] int (*)[10]
&a int (*)[10][10]
*a int [10] int *
a[i] int [10] int *
&a[i] int (*)[10]
*a[i] int
a[i][j] int
&a[i][j] int *
Also,
sizeof a == sizeof (int) * 10 * 10
sizeof &a == sizeof (int (*)[10][10])
sizeof *a == sizeof (int) * 10
sizeof a[i] == sizeof (int) * 10
sizeof &a[i] == sizeof (int (*)[10] )
sizeof *a[i] == sizeif (int)
sizeof a[i][j] == sizeof (int)
sizeof &a[i][j] == sizeof (int *)
Note that the different pointer types int (*)[10][10], int (*)[10], and int * don't have to be the same size or have the same representation, although on the platforms I'm familiar with they do.
The address of the first element of the array is the same as the address of the array itself; thus, all of a, &a, a[0], &a[0], and &a[0][0] will yield the same value, but the types will be different (as shown in the table above).
So, assume we add the following declarations:
int *p0 = &a[0][0]; // equivalent to int *p0 = a[0];
int (*p1)[10] = &a[0]; // equivalent to int (*p1)[10] = a;
int (*p2)[10][10] = &a;
All of p0, p1, and p2 initially have the same value, which is the address of the first element in a; however, because of the different pointer types, the results operations involving pointer arithmetic will be different. The expression p0 + 1 will yield the address of the next int object (&a[0][1]). The expression p1 + 1 will yield the address of the next 10-element array of int (&a[1][0]). And finally, the expression p2 + 1 will yield the address of the next 10-element array of 10-element array of int (effectively, &a[11][0]).
Note the types of p1 and p2; neither is a simple int *, because the expressions being used to initialize them are not that type (refer to the first table).
Note the pattern; for an array type, the simpler the expression, the more complicated the corresponding type will be. The expression a does not refer to a single int object; it refers to a 10x10 array of int objects, so when it appears in an expression, it is treated as a pointer to an array of integers, not a pointer to a single integer.
The compiler knows that "a" is a pointer to ten integers. If you don't declare the dimensions, then the compiler sees the new pointer as a pointer to an unknown number of integers. This will work in your case, but it will generate a compiler warning because the compiler sees them as incompatible pointers. The syntax for what you are trying to do (without generating a compiler warning) is:
int a[10][10];
int *p1 = &a[0][0];
int (*p2)[10] = a;
printf("p1: %p p2: %p\n", p1, p2);
One reason this is important is pointer arithmetic:
p1++; //move forward sizeof(int) bytes
p2++; //move forward sizeof(int) * 10 bytes
You understanding is close, the difference is the type information. Pointer does has its type. For example int* p, the pointer type is int*, as int a[10][10], the corresponding pointer type is int *[10][10].
In your example, p and a do point to the same address, but they're different type, which matters when perform arithmetic operation on them.
Here's an example from this URL
Suppose now that we define three pointers :
char *mychar;
short *myshort;
long *mylong;
and that we know that they point to the memory locations 1000, 2000, and 3000, respectively.
Therefore, if we write:
++mychar;
++myshort;
++mylong;
mychar, as one would expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each been incremented only once. The reason is that, when adding one to a pointer, the pointer is made to point to the following element of the same type, and, therefore, the size in bytes of the type it points to is added to the pointer.
You are right, you can assign the array itself to the pointer:
int a[10][10] = {[0][0]=6,[0][1]=1,[1][0]=10,[1][1]=11};
int b[10][10][10] = {[0][0][0]=8,[0][0][1]=1,[0][1][0]=10,[1][0][0]=100};
int *p, *q, *r, *s;
p = &a[0][0];
q = a; // what you are saying
r = &b[0][0][0];
s = b; // what you are saying
printf("p= %p,*p= %d\n",p,*p);
printf("q= %p,*q= %d\n",q,*q);
printf("r= %p,*r= %d\n",r,*r);
printf("s= %p,*s= %d\n",s,*s);
And the output is:
p= 0xbfdd2eb0,*p= 6
q= 0xbfdd2eb0,*q= 6
r= 0xbfdd3040,*r= 8
s= 0xbfdd3040,*s= 8
They point to the same address, regardless of the dimension of the matrix. So, what you are saying is right.
Well in 2D array, the outcome of *a and a is the same, they all point to the first address of this 2D array!
But if you want to define a pointer to point to this array, you could use int (*ptr)[10] for example.
You are right, 1D and 2D share the same structure, but 2D has some additional manipulation on pointers like above.
So all in all, in 2D array, a, *a and &a[0][0] prints the same address, but their usages may vary.
Like this:
#include<stdio.h>
int main() {
int a[10][10];
int *pa1 = &a[0][0];
int *pa2 = *a;
printf("pa1 is %p\n", pa1);
printf("pa2 is %p\n", pa2);
printf("Address of a is %p\n", a);
// pointer to array
int (*pa3)[10];
pa3 = a;
printf("pa3 is %p\n", pa3);
return 0;
}
They print the same address.

Resources