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

#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.

Related

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.

What does *p mean when **p is already declared

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.

Why the address of pointer of an Array is the same of the data stored in that pointer?

If you try that piece of code
#include<stdio.h> int main() {
// Pointer to an integer
int *p;
// Pointer to an array of 5 integers
int (*ptr)[5];
int arr[] = { 3, 5, 6, 7, 9 };
// Points to 0th element of the arr.
// Points to the whole array arr.
ptr = &arr;
printf("p = %p, address of P = %p\n", p, &p);
return 0; }
You will get something like p = 0x7fff8e9b4370, P address = 0x7fff8e9b4340
which means the address of pointer P is something and the data inside it is another
but if you try the same with the pointer of the array like this
#include<stdio.h> int main() {
// Pointer to an integer
int *p;
// Pointer to an array of 5 integers
int (*ptr)[5];
int arr[] = { 3, 5, 6, 7, 9 };
// Points to 0th element of the arr.
p = arr;
// Points to the whole array arr.
ptr = &arr;
printf("arr = %p, arr address = %p\n", arr, &arr);
return 0; }
You will get something like arr = 0x7ffda0a04310, arr address = 0x7ffda0a04310
So how come that a pointer data is the same the pointer Address in memory ?!! when we dereference the address of the arr pointer we should get the number 3 but as i understand from this is the address location 0x7ffda0a04310 in the memory has 0x7ffda0a04310 as a data
so where i am mistaken ?
printing p means print p's value, while p's value is address of a integer number or address of an integer array.
printing &p means you print location of p on memory.
printing arr will show address of first element of the array, it is &arr[0].
printing &arr will show location of arr on memory, it is also adress of first element of the array
So printing p will be different with printing &p.
arr and &arr are different types but it will give you the same result.
This is because when you use the symbol of an array, it actually evaluates to &arr (address to first element). So because of this arr and &arr are the same address (but not the same type!).
arr is of type int*
&arr is of type int(*)[5]
The difference is when you do pointer arithmetics. Incrementing arr will go to the address of the next element. So *(arr+1) is essentially the same as arr[1].
Incrementing &arr jumps over the whole array (incrementing a pointer always jumps the whole size of the type)
What you've discovered is that the address of an array is the same as the address of its first member.
When you use the array arr in an expression, in most cases it decays to a pointer to its first element. So arr in an expression is equivalent to &arr[0]. Since the members of arr have type int, the expression &arr[0] (and by extension arr) have type int *.
In some cases however this decay does not happen. One of those is when an array is the operand of the & operator. So the expression &arr has type int (*)[5], i.e. a pointer to a array of int of size 5.
As for why the values of these two address are the same, it makes sense if you look at it:
arr
-------
0x7ffda0a04310 | 0 |
-------
| 0 |
-------
| 0 |
-------
| 0 |
-------
0x7ffda0a04314 | 1 |
-------
| 1 |
-------
| 1 |
-------
| 1 |
-------
...
Looking at this, you can see that the array itself and the array's first element start at the same address.
So arr (as an expression) has type int * while &arr has type int(*)[5], but both have the same value.

How do you get the address of array elements given the address of the array itself in C?

*edited to clarify that the array is unknown
If the address of unknown integer array is 0x00006ffd29c78e70 (and an integer is 4 bytes), what is the address of element array[1]?
Many thanks in advance.
The address of the array is also the address of its first element. This is because the array itself in memory consists solely of each of its elements (starting at index 0) in turn. Therefore if A is an array, &A[0] points to the same memory as A. (Note that there is a technical difference between an array of integers type and a pointer to an integer type, though they are in many cases interchangeable as the former decays into the latter under certain circumstances which are beyond the scope of this question; this is why I described them as pointing both to the same memory).
You asked about the first element, and then referred to A[1]. Note that A[1] is the second element. A[0] is the first element.
So in your particular example, you could do:
int *A = (int *)0x00006ffd29c78e70;
int *A1 = &A[1]; // points to second element
int foo = *A1; // second element contents
or using pointer arithmetic
int *A = (int *)0x00006ffd29c78e70;
int *A1 = A+1; // points to second element
int foo = *A1; // second element contents
Note the +1 does not add one to the (byte) address, but increments the pointer by one int.
Note I have written int above - use the correct integer data type to represent your 4 byte integer.
If 0x00006ffd29c78e70 is the address of a valid array of ints then you can assign it to a pointer:
int *p = (int*)0x00006ffd29c78e70;
then p[1] will give you the next element (second) in that array.
Elements are at
unsigned char *addressofarray = whatever;
unsigned char *secondelement = addressofarray + sizeof arrayelement;
unsigned char *nthelement = addressofarray + n * sizeof arrayelement;
you just got a pointer to acess any thing in array as:
int *ptr = (int*) 0x00006ffd29c78e70;
you can acess any element as:
*(ptr+i) //i is the index

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