the difference between array identifier and address of array identifier - c

Following program would state my doubt clearly I think,so I posted the program:
#include <stdio.h>
int main() {
int a[]={1,2,3,4,5};
if(&a[0] == a)
printf("Address of first element of an array is same as the value of array identifier\n");
if(&a == a)
printf("How can a value and address of an identifier be same?!");
return 0;
}
This is the link to output: http://ideone.com/KRiK0

When it is not the subject of the sizeof or unary & operators, an array evaluates to a (non-lvalue) pointer to its first element.
So &a is the address of the array a, and a evaluates to the address of the first element in the array, a[0].
That the address of the array and the address of the first element in the array are the same is not surprising (that is, they point to the same location even though they have different types); the same is true of structs as well. Given:
struct {
int x;
int y;
} s;
Then &s and &s.x point to the same location (but have different types). If converted to void * they will compare equal. This is exactly analogous with &a and &a[0] (and consequently just a).

C++ has an implicit conversion between an array reference and a pointer. This has been asked many times before, see for example this SO question.

In C, you can get away with comparing two different types of pointers, but your compiler should give you a warning.

If I get your question right. Your int a[]={1,2,3,4,5}; I believe only stores the address of element 0 so putting this if(&a[0] == a)
is probably not required. The c string theory states that an array identifier without the bracket is the address of the first element of the characters. "a" is not defined in the program. it would probably give you a stack error. I would write it this way if(&a == a[]){printf("------"); this would only compare the address of the pointer to the address of the first element of the array.

Related

Difference between &ar[0][0] and ar [duplicate]

I am having a tough time understanding the type and use of the name of the array in C. It might seems a long post but please bear with me.
I understand that the following statement declares a to be of type int [] i.e array of integers.
int a[30];
While a also points the first element of array and things like *(a+2) are valid. Thus, making a look like a pointer to an integer. But actually the types int [] and int* are different; while the former is an array type and later is a pointer to an integer.
Also a variable of type int [] gets converted into a variable of type int* when passing it to functions; as in C arrays are passed by reference (with the exception of the sizeof operator).
Here comes the point which makes me dangle. Have a look at the following piece of code:
int main()
{
int (*p)[3];
int a[3] = { 5, 4, 6 };
p = &a;
printf("a:%d\t&a:%d\n",a,&a);
printf("%d",*(*p + 2));
}
OUTPUT:
a:2686720 &a:2686720
6
So, how does the above code work? I have two questions:
a and &a have the same values. Why?
What exactly does int (*p)[3]; do? It declares a pointer to an array, I know this. But how is a pointer to an array different from the pointer to the first element of the array and name of the array?
Can anyone clarify things up? I am having a hell of a lot of confusions.
I know that I should use %p as a placeholder instead of using %d for printing the value of pointer variables. As using the integer placeholder might print truncated addresses. But I just want to keep things simple.
Other answers already explained the issue. I am trying to explain it with some diagram. Hope this will help.
When you declare an array
int a[3] = {5, 4, 6}
the memory arrangement looks like
Now answering your question:
a and &a have the same values.How?
As you already know that a is of array type and array name a becomes a pointer to first element of array a (after decay),i.e it points to the address 0x100. Note that 0x100 also is the starting address of the memory block (array a). And you should know that, in general, the address of the first byte is said to be the address of the variable. That is, if a variable is of 100 bytes, then its address is equal to the address of its first byte.
&a is address of the entire memory block, i.e it is an address of array a. See the diagram:
Now you can understand why a and &a both have same address value although both are of different type.
What exactly it does int (*p)[3]; Declares a pointer to an array,i know this.But,how a pointer to an array is different from the pointer to the first element of the array and name of the array?
See the above figure, it is explained clearly how pointer to an array is different from the pointer to an array element.
When you assign &a to p, then p points to the entire array having starting address 0x100.
NOTE: Regarding to the line
... as in C arrays are passed by references (with exception of sizeof function).
In C, arguments are passed by value. No pass by reference in C. When an ordinary variable is passed to a function, its value is copied; any changes to corresponding parameter do not affect the variable.
Arrays are also passed by value, but difference is that the array name decays to pointer to first element and this pointer assigned to the parameter (here, pointer value is copied) of the function; the array itself isn't copied.
In contrast to ordinary variable, an array used as an argument is not protected against any change, since no copy is made of the array itself, instead copy of pointer to first element is made.
You should also note that sizeof is not a function and array name does not act as an argument in this case. sizeof is an operator and array name serves as an operand. Same holds true when array name is an operand of the unary & operator.
a and &a have the same values.How?
They have the same value but different types. Array objects have no padding between elements (before or after) so the address of the array and the address of the first element of the array are the same.
That is:
(void *) a == (void *) &a
What exactly it does int (*p)[3]; Declares a pointer to an array,i know this.But,how a pointer to an array is different from the pointer to the first element of the array and name of the array?
These are two different pointer types. Take for example, pointer arithmetic:
a + 1 /* address of the second element of the array */
&a + 1 /* address one past the last element of the array */
EDIT: due to popular demand I added below some information about conversion of arrays.
With three exceptions, in an expression an object of type array of T is converted to a value of type pointer to T pointing to the first element of the array. The exceptions are if the object is the operand of sizeof or & unary operator or if the object is a string literal initializing an array.
For example this statement:
printf("a:%d\t&a:%d\n", a, &a);
is actually equivalent to:
printf("a:%d\t&a:%d\n", &a[0], &a);
Also please note that d conversion specifier can only be use to print a signed integer; to print a pointer value you have to use p specifier (and the argument must be void *). So to do things correctly use:
printf("a:%p\t&a:%p\n", (void *) a, (void *) &a);
respectively:
printf("a:%p\t&a:%p\n", (void *) &a[0], (void *) &a);
a corresponds to the pointer pointing at 0th element of the array. Whereas,the same is the case with &a.It just gives the starting address of the array.
As,a --> pointer pointing to starting element of array a[],it does not know about other element's location..
&a --->address location for storing array a[] which stores first element location,but knows every element's location.
Similarly,other elements location will be (a+2),(a+4) and so upto the end of the array.
Hence,you got such result.
int (*p)[3] is a pointer to the array. had it been int *p[3],it would been meant entirely different. It'd have meant an array of pointers which would have been totally different from this context.
Pointer to an array will automatically take care of all the other
elements in the array.In this case,your's is (p);
Whereas,the pointer to the first element of the array,i.e., a will
only know about first element of the array.You'll have to manually
give pointer arithmetic directions to access next elements.See,in this
case---we can get second element from a by adding 2 to a,i.e.
a+2,third element by adding 4 to a,i.e., a+4 and so on. // mind the
difference of two as it is an integer array!
In answer to question 1, this is simply an aspect of the C language as designed, unlike most other modern languages C/C++ allows direct manipulation of addresses in memory and has built in facilities to 'understand' that. There are many articles online that explain this better than I could in this small space. Here is one and I am sure there are many others: http://www.cprogramming.com/tutorial/c/lesson8.html
From C99 Standard n1124 6.3.2.1 p3
Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
a and &a have the same value because a long time ago you were required to use the address operator & on arrays to get the array's address, but it is no longer necessary. The name of the array (a in this case) these days just represents the memory address of the array itself, which is also what you get from &a. It's a shorthand that the compiler handles for you.

What is the value about these arrays in c?

#include<stdio.h>
#include<stdlib.h>
int main(){
int myChr[4][8];
printf("%x\n",myChr);
printf("%x\n",&myChr);
printf("%x\n",*myChr);
return 0;
}
After executing the above program, I get the same address as output. Do they own different value or all of them have same value? How to prove that? (*Maybe need to assume values to array, I don't know)
myChr is the address on the stack of your array.
&mychr, in this case, is probably going to give you the same value as it is the address of the pointer on the stack.
*myChr is the address of 1st entry of myChr[4][8] entry, which in the case is still the original address.
**myChar would give you the value of myChr[0][0] - in this case garbage as you have not actually assigned anything to your array.
myChar is a int [4][8].
In the printf expression:
myChar is of type int (*)[8] (after application of C array to pointer conversion rule from int [4][8])
&myChar is of type int (*) [4][8]
*myChar is of type int * (after application of C array to pointer conversion rule from int [4])
All the expressions have different types but they point to the same memory address, that is:
(void *) myChar == (void *) &myChar == (void *) *myChar
Note that the valid way to print a pointer value is to use p conversion specifier and cast the pointer to void * if it is of a different type.
Arrays are simply named extents of memory. So the address of an array is the address of the extent it occupies. At the same time it is the address of the first element of the array because it occupies the initial part of the extent.
Thus you have:
this statement
printf("%x\n",myChr);
displays the address of the first element of the array because array name is implicitly converted to pointer to its first element;
this statement
printf("%x\n",&myChr);
displays the address of the array that is the same address as above because it is the address of the allocated extent;
this statement
printf("%x\n",*myChr);
displays the same address. Why? As I have already said the name of the array is implicitly converted to pointer to its first element. The element of the array is in turn a one-dimensional array. So in expression this one-dimensional array *myChr (the first element of the original two-dimensional array) in turn is converted to pointer to its first element.
So in all three cases you display this address :)
&myChr[0][0]

Pointer and array 'a' and '&a' giving same output? [duplicate]

I am having a tough time understanding the type and use of the name of the array in C. It might seems a long post but please bear with me.
I understand that the following statement declares a to be of type int [] i.e array of integers.
int a[30];
While a also points the first element of array and things like *(a+2) are valid. Thus, making a look like a pointer to an integer. But actually the types int [] and int* are different; while the former is an array type and later is a pointer to an integer.
Also a variable of type int [] gets converted into a variable of type int* when passing it to functions; as in C arrays are passed by reference (with the exception of the sizeof operator).
Here comes the point which makes me dangle. Have a look at the following piece of code:
int main()
{
int (*p)[3];
int a[3] = { 5, 4, 6 };
p = &a;
printf("a:%d\t&a:%d\n",a,&a);
printf("%d",*(*p + 2));
}
OUTPUT:
a:2686720 &a:2686720
6
So, how does the above code work? I have two questions:
a and &a have the same values. Why?
What exactly does int (*p)[3]; do? It declares a pointer to an array, I know this. But how is a pointer to an array different from the pointer to the first element of the array and name of the array?
Can anyone clarify things up? I am having a hell of a lot of confusions.
I know that I should use %p as a placeholder instead of using %d for printing the value of pointer variables. As using the integer placeholder might print truncated addresses. But I just want to keep things simple.
Other answers already explained the issue. I am trying to explain it with some diagram. Hope this will help.
When you declare an array
int a[3] = {5, 4, 6}
the memory arrangement looks like
Now answering your question:
a and &a have the same values.How?
As you already know that a is of array type and array name a becomes a pointer to first element of array a (after decay),i.e it points to the address 0x100. Note that 0x100 also is the starting address of the memory block (array a). And you should know that, in general, the address of the first byte is said to be the address of the variable. That is, if a variable is of 100 bytes, then its address is equal to the address of its first byte.
&a is address of the entire memory block, i.e it is an address of array a. See the diagram:
Now you can understand why a and &a both have same address value although both are of different type.
What exactly it does int (*p)[3]; Declares a pointer to an array,i know this.But,how a pointer to an array is different from the pointer to the first element of the array and name of the array?
See the above figure, it is explained clearly how pointer to an array is different from the pointer to an array element.
When you assign &a to p, then p points to the entire array having starting address 0x100.
NOTE: Regarding to the line
... as in C arrays are passed by references (with exception of sizeof function).
In C, arguments are passed by value. No pass by reference in C. When an ordinary variable is passed to a function, its value is copied; any changes to corresponding parameter do not affect the variable.
Arrays are also passed by value, but difference is that the array name decays to pointer to first element and this pointer assigned to the parameter (here, pointer value is copied) of the function; the array itself isn't copied.
In contrast to ordinary variable, an array used as an argument is not protected against any change, since no copy is made of the array itself, instead copy of pointer to first element is made.
You should also note that sizeof is not a function and array name does not act as an argument in this case. sizeof is an operator and array name serves as an operand. Same holds true when array name is an operand of the unary & operator.
a and &a have the same values.How?
They have the same value but different types. Array objects have no padding between elements (before or after) so the address of the array and the address of the first element of the array are the same.
That is:
(void *) a == (void *) &a
What exactly it does int (*p)[3]; Declares a pointer to an array,i know this.But,how a pointer to an array is different from the pointer to the first element of the array and name of the array?
These are two different pointer types. Take for example, pointer arithmetic:
a + 1 /* address of the second element of the array */
&a + 1 /* address one past the last element of the array */
EDIT: due to popular demand I added below some information about conversion of arrays.
With three exceptions, in an expression an object of type array of T is converted to a value of type pointer to T pointing to the first element of the array. The exceptions are if the object is the operand of sizeof or & unary operator or if the object is a string literal initializing an array.
For example this statement:
printf("a:%d\t&a:%d\n", a, &a);
is actually equivalent to:
printf("a:%d\t&a:%d\n", &a[0], &a);
Also please note that d conversion specifier can only be use to print a signed integer; to print a pointer value you have to use p specifier (and the argument must be void *). So to do things correctly use:
printf("a:%p\t&a:%p\n", (void *) a, (void *) &a);
respectively:
printf("a:%p\t&a:%p\n", (void *) &a[0], (void *) &a);
a corresponds to the pointer pointing at 0th element of the array. Whereas,the same is the case with &a.It just gives the starting address of the array.
As,a --> pointer pointing to starting element of array a[],it does not know about other element's location..
&a --->address location for storing array a[] which stores first element location,but knows every element's location.
Similarly,other elements location will be (a+2),(a+4) and so upto the end of the array.
Hence,you got such result.
int (*p)[3] is a pointer to the array. had it been int *p[3],it would been meant entirely different. It'd have meant an array of pointers which would have been totally different from this context.
Pointer to an array will automatically take care of all the other
elements in the array.In this case,your's is (p);
Whereas,the pointer to the first element of the array,i.e., a will
only know about first element of the array.You'll have to manually
give pointer arithmetic directions to access next elements.See,in this
case---we can get second element from a by adding 2 to a,i.e.
a+2,third element by adding 4 to a,i.e., a+4 and so on. // mind the
difference of two as it is an integer array!
In answer to question 1, this is simply an aspect of the C language as designed, unlike most other modern languages C/C++ allows direct manipulation of addresses in memory and has built in facilities to 'understand' that. There are many articles online that explain this better than I could in this small space. Here is one and I am sure there are many others: http://www.cprogramming.com/tutorial/c/lesson8.html
From C99 Standard n1124 6.3.2.1 p3
Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
a and &a have the same value because a long time ago you were required to use the address operator & on arrays to get the array's address, but it is no longer necessary. The name of the array (a in this case) these days just represents the memory address of the array itself, which is also what you get from &a. It's a shorthand that the compiler handles for you.

Different assignment of base address to a pointer

I am referring a book Named "Let Us c" By Yashwant Kanetkar.
I am a little confused about this example where he assigns a base address to a pointer.
Example:
int x[10] = {1,2,3,4,5,6,7,8,9,10,11};
int *p = x; // base address of x assigned to *p
//************//
int z[10] = {1,2,3,4,5,6,7,8,9,10,11};
int *q = &z[0]; // base address of z assigned to *q
If both have the same functionality then why is different notation used? Is there any other reason for doing this?
When you use the name of an array in an assignment, like in the first case, the array decays to a pointer to the address of the first element.
In the second case, the expression z[0] gives you the first element of the array by value and when you prepend an ampersand & to the expression, you get the address of that element which renders the same result of the first case.
Both are effectively same. By using the base index, you can iterate through the memory allocated for the array. In this case accessing a[10]; is not correct since array was defined to hold maximum of 10 elements.
The second notation is mostly used to assign the address of the particular element,, &x[n]
The two different notations for the same result illustrate that x, the array, is truly just a pointer while x[0], an element, is an actual value. This is just one of the many examples of multiple ways of saying the same thing in C (kind of like English).

array of pointers

Consider the following code:
#include <stdio.h>
int main()
{
static int a[]={0,1,2,3,4};
int *p[]={a,a+1,a+2,a+3}; /* clear up to this extent */
printf(("%u\n%u\n%u",p,*p,*(*p))); /* how does this statement work? */
return 0;
}
Also is it necessary to get the value of addresses through %u,or we can use %d also?
Okay, you've created an array of integers and populated it with the integers from 0 to 4. Then you created a 4 element array of pointers to integers, and initialized it so its four elements point to the first four elements of a. So far, so good.
Then the printf is very strange. printf is passed a single argument, namely ("%u\n%u\n%u",p,p,(*p)). This is a comma-expression which means that the comma-separated expressions will be calculated in turn, and only the last one returned. Since the very first thing is a literal, and not an expression, I'd expect it to generate an error. However, without the extraneous parentheses, you have:
printf("%u\n%u\n%u\n",p, *p, *(*p));
This is legal. Three values are passed to printf, interpreted as unsigned integers (which actually only works on some systems, since what you are actually passing in are pointers in the first two cases, and they aren't guarateed to be the same size as unsigned ints) and printed.
Those values are p, *p and **p. p is an array, and so the value of p is the address of the array. *p is what p points to, which are the values of the array. *p is the first value, *(p+1) is the second value, etc. Now *p is the value stored in p[0] which is the address of a[0], so another address is printed. The third argument is **p which is the value stored at (*p), or a[0], which is 0
Do you have an extra pair of parens in your printf statement?
Anyway, you can think of this statement:
printf("%u\n%u\n%u",p,*p,*(*p));
like following a trail of pointers.
p is the pointer itself, printing it should print out the pointer's value which is the address of what it points to. In your case its an array of (int *)'s.
*p is a dereferencing operation. It allows access to the object that p points to. In the other answers you see notes made about *p being equivalent to p[0]. That's because p is pointing to the beginning of your structure, which is the start of the array.
**p is a dereferencing operation on the pointer object that p points to. Extending the example in the previous point, you can say that **p is equivalent to *(p[0]) which is equivalent to *(a) which is equivalent to a[0].
One tip that might help you when trying to decipher these sorts of statements is that keep in mind the precedence rules of C and insert parens between expressions in the statement to break up the statement. For the **p, inserting parens would do this: *(*p) which makes it clear that what you're doing is to follow two pointers to the final destination.
With those extra parentheses, the commas become comma operators so only the final **p is passed to printf. Since printf expects its first argument to be a pointer to a character string, and on most systems pointers
and integers have the same size, so the integer 0 is interpreted as a NULL pointer, and printf prints nothing at all. Or it crashes. That's the trouble with undefined behavior.
Your printf() arguments work like so:
p is an address (it's an array of pointers)
*p is also an address (it's equivalent to p[0], which is just a)
*(*p) is an integer (it's a[0])
My memory on C pointers is a tiny bit rusty, but let me see if I can recall.
p should be a memory location, it points to nothing else, other than p.
*p dereferences (goes to the memory location and returns the value there) p. since p itself is a pointer to pointers (*p[] can be also written as **p) when we dereference p we get the first value in the array definition, or the address of a.
**p dereferences *p. *p is the address of a. If we dereference that, we'll get the value we put in the first location of a, which is 0

Resources