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.
Related
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.
Code
short **p = (short **)malloc(sizeof(short *));
*p = malloc(sizeof(short));
**p = 10;
printf("**p = %d", **p);
Output
**p = 10
In this code, a multiple pointer **p is declared and *p is used without any declaration(maybe it's by **p).
What does *p mean in my case? Sorry for very simple question.
I saw C standard and stack overflow, but I couldn't find out something.
For any array or pointer p and index i, the expression p[i] is exactly equal to *(p + i) (where * is the unary dereference operator, the result of it on a pointer is the value that the pointer is pointing to).
So if we have p[0] that's then exactly equal to *(p + 0), which is equal to *(p) which is equal to *p. Going backwards from that, *p is equal to p[0].
So
*p = malloc(sizeof(short));
is equal to
p[0] = malloc(sizeof(short));
And
**p = 10;
is equal to
p[0][0] = 10;
(**p is equal to *(*(p + 0) + 0) which is equal to *(p[0] + 0) which is then equal to p[0][0])
It's important to note that the asterisk * can mean different things in different contexts.
It can be used when declaring a variable, and then it means "declare as pointer":
int *p; // Declare p as a pointer to an int value
It can be used to dereference a pointer, to get the value the pointer is pointing to:
*p = 0; // Equal to p[0] = 0
And it can be used as the multiplication operator:
r = a * b; // Multiply the values in a and b, store the resulting value in r
short **p = (short **)malloc(sizeof(short *));
This line declares a pointer to a pointer p. Additionally the value of p is set to the return value from malloc. It is equivalent to
short **p;
p = (short **)malloc(sizeof(short *));
The second line
*p = malloc(sizeof(short));
Here *p is the value of p. *p is of type pointer. *p is set to the return value of malloc. It is equivalent to
p[0] = malloc(sizeof(short));
The third line
**p = 10;
**p is the value of the value of p. It is of type short. It is equivalent to
p[0][0] = 10
In effect what the code above does is to allocate a 2D array of short, then allocate memory for the first row, and then set the element p[0][0] to 10.
As a general comment on your code, you should not use typecast in malloc. See Do I cast the result of malloc?
What does *p mean when **p is already declared?
short **p = (short **)malloc(sizeof(short *));
(better written as)
short **p = malloc (sizeof *p);
Declares the pointer-to-pointer-to short p and allocates storage for a signle pointer with malloc and assigns the beginning address for that block of memory to p. See: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
*p = malloc(sizeof(short));
(equivalent to)
p[0] = malloc (sizeof *p[0]);
Allocates storage for a single short and assigns the starting address for that block of memory to p[0].
**p = 10;
(equivalent to)
*p[0] = 10;
(or)
p[0][0] = 10;
Assigns the value 10 to the dereference pointer *p[0] (or **p or p[0][0]) updating the value at that memory address to 10.
printf("**p = %d", **p);
Prints the value stored in the block of memory pointed to by p[0] (the value accessed by dereferencing the pointer as *p[0] or **p)
The way to keep this straight in your head, is p is a single pointer of type pointer-to-pointer-to short. There are 2-level of indirection (e.g. pointer-to-pointer). To remove one level of indirection, you use the unary * operator, e.g.
*p /* has type pointer-to short */
or the [..] also acts as a dereference such that:
p[0] /* also has type pointer-to short */
You still have a pointer-to so you must remove one more level of indirection to refernce the value stored at the memory location pointed to by the pointer. (e.g. the pointer holds the address where the short is stored as its value). So you need:
**p /* has type short */
and
*p[0] /* also has type short */
as would
p[0][0] /* also has type short */
The other piece to keep straight is the type controls pointer-arithmetic. So p++ adds 8-bytes to the pointer-to-ponter address so it now points to the next pointer. If you do short *q = (*p)++; (or short *q = p[0]++, adds 2-bytes to the address for the pointer-to-short, soqnow points to the nextshortin the block of memory beginning at*p(orp[0]`). (there is no 2nd short because you only allocated 1 -- but you get the point)
Let me know if you have further questions.
Let me put it in different way,
consider an example,
int x;
int *y = &x;
int **z = &y;
x = 10;
Which simplifies to this,
Note: Only for illustration purpose I have chosen address of x,y,z as 0x1000,0x2000,0x3000 respectively.
What does *p mean in my case?
In short the snippetshort **p = (short **)malloc(sizeof(short *)); is dynamically allocating a pointer to a pointer of type short i.e same asy in my example.
int r = 50;
int *p;
int **k;
int ***m;
printf( "r: %d ", r );
p = &r;
k = &p;
m = &k;
***m = 100; //line 9
printf( "r: %d\n", r );
When there is only one pointer, I can understand that we take 100 and we assign it to the variable at the address which is being held by the pointer. But what exactly is happening step by step when we do this with more than one pointer level? (line 9)
int *p=&r: p is a pointer-to-int, and it takes the address of r.
int **k=&p: k is a pointer-to-( pointer-to-int ), and it takes the address of p.
int ***m=&k: m is a pointer-to-( pointer-to-( pointer-to-int ) ), and it takes the address of k.
When you do ***m = 100, you are "unwrapping" the pointers, and finally you end up with just int.
The reason pointer-to-pointer works, is that a pointer is a variable, too. It just stores addresses. So a pointer-to-pointer is the address of a variable that contains an address.
In this diagram v is the variable, containing 100. Its address is 1000. ptr contains the address of v, which is 1000. pptr contains the addres of ptr, which is 720.
Pointer to Pointer or Multiline pointer
When address of r is passed to pointer p!
Then if you passing the address of p to another pointer k then for the dereferencing the actual value you want to dereference it two times to get actual value of r and so on.
Take a look at the image
#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.
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;