So I know that pointers are variables that store the address(s) of some other variables. But the thing that I am confused with is this:
I know that using the name of the array in most of the contexts would decay it to the base address of the element. But I get confused here:
When we declare an array say int arr[5], and then say scanf("%d",arr+1), here arr is an address right? We did not explicitly store it in any variable i.e, a pointer. So how does arr+1 arithmetic work similar to pointer arithmetic? Also this: *(arr+1) would give us the value in the address arr+1. I do realize that we can dereference an address, but here I kind of find it difficult to work with it because I kind of lose the "hey this pointer points to this address.." here. And my final question would be, is this the exact way that we can differentiate an address from a random value in a computer? Like arr+1 leads to the address of the next integer in this case, and not normal +1 (pointer arithmetic basically).
I hope that my question does not have any ambiguity.
Your problem starts with this misunderstanding:
So I know that pointers are variables that store the address(s) of some other variables.
"Pointer" is a type category. There are values of pointer types, which are also referred to as "addresses", and there also variables declared to hold such values. This is entirely analogous to there being values of type int and variables declared to hold int values. Also, just as we might refer to either an int value or an int variable as "an int", people can and do refer to both pointer values and pointer variables as "pointers".
Additionally, it is a bit imprecise and a bit misleading to say that pointer values are the addresses of variables. They are the addresses of objects, and although in-scope variables do represent objects, not all objects correspond to variables.
When we declare an array say int arr[5], and then say scanf("%d",arr+1), here arr is an address right?
When the scanf call is evaluated, the array value of arr is automatically converted to a pointer value, the address of the first array element.
We did not explicitly store it in any variable i.e, a pointer.
You do not need to store a pointer value in a variable in order to use it in an expression. In fact, just the opposite: if you want to use the value of a pointer variable in an arithmetic expression, you must first read the value from it -- a process called "lvalue conversion". The same applies to variables of all types and expressions involving most operators. Most operations are defined in terms of values, and variables are just one way to convey those.
So how does arr+1 arithmetic work similar to pointer arithmetic?
There is no "similar to" here. It is pointer arithmetic. arr is automatically converted to a pointer value. That value is a suitable operand for the addition operator, provided that the other operand is of integer type. This is a pointer arithmetic expression.
Also this: *(arr+1) would give us the value in the address arr+1.
Yes, though it would be more idiomatic to say the value at address arr+1.
I do realize that we can dereference an address, but here I kind of find it difficult to work with it because I kind of lose the "hey this pointer points to this address.."
Well, most people would write *(arr+1) as arr[1], which is 100% equivalent, but easier to read and usually clearer. Other than that, I'm not sure what you're asking, if anything.
is this the exact way that we can differentiate an address from a random value in a computer? Like arr+1 leads to the address of the next integer in this case, and not normal +1 (pointer arithmetic basically).
How a C program interprets a given sequence of bytes is determined by the data type it attributes to the sequence. That is exactly the function of data typing. There is no difference discernable in the underlying physical memory, it is all a manner of the program's interpretation. x+1 is pointer arithmetic if x has pointer type, including as the result of automatic conversion from an array. It is integer addition if x has type int, long, etc.. It is floating-point addition if x has type double, float, or long double.
Let's suppose we have:
int n = 1;
int arr[100];
arr + n: yes this is an address.
arr + n: yes, we do doing pointer arithmetic here.
arr + n is the same thing as &arr[n].
*(arr + n) is the same thing as arr[n].
Example of pointer arithmetic:
Let's suppose the size of an int is 4 bytes and arr is the address 0x10000:
arr + n is 0x10000 + n * 4
sor for example arr+2 is the address 0x10008
Your last question is somewhat unclear but if you understood the above it should be clear.
Related
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.
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.
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.
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.
Edit: The similar question asked before has not addressed some perspectives related to the issue.
In the ANSI C book by Kernighan and Ritchie, they say that the following are equivalent
a[i]
*(a+i)
I don't see how this can be true for elements that occupy more than one address space, e.g. structs.
Please explain? Edit: Thank you for all answers, but I don't quite understand it. It would seem I am suffering the same confusion as #CucumisSativus from his answer and comments to it.
Say sizeof(*a) is 3. If for some reason I wanted to access the middle byte of the first element in a, I had thought this is how I would do it: *(a+1).
Say the address of a is 10, and the sizeof each element is 20. And say we want to get the pointer to the second element. As I see it, we could do this: p = (10 + 20). I thought this would be equivalent to &a[1].
I'm having real trouble explaining what I don't understand!!
Pointer arithmetic is treated differently than regular integer arithmetic in C. Adding an integer i to a pointer p advances the memory address by i * sizeof(*p), i.e., by i times the size of the type being pointed to.
As a potentially interesting, but practically useless, sidenote: due to the definition of p[i] as *(p+i), the expression i[p] is also equivalent to the same…
The + operator is not meant to be the next element in the address space.
The increment is defined by the size of the data type involved. Thus, a + 1 will refer to the next int if a is a pointer to an integer, and will refer to the next struct if a is a pointer to a struct.
Lets say we have an Integer pointer and a Character pointer as follows
int *a;
char *b;
Now assume that a is stored at location 10000
and b is stored at location 20000
So by doing the following operations
*(a+1) : It will return the value contained in address 10004 i.e. (10000+4)
*(b+1) : It will return the value contained in address 20001 i.e. (20000+1)
Reason:
Pointer addition is different from regular arithmetic addition. If you add 1 to an integer pointer it advances the pointer to a location by the size of the integer. So in this case it advances the pointer to 10004. Since character is only 1 byte long it advances the pointer by 1 byte.
a+i is translated to something like this in pseudo code
*(a+i*sizeof(variableType))
I read more of K&R and found the missing pieces to the puzzle, allowing me to rationalise what's happening. (Whether I'm correct or not is open to debate!)
From what I gather, the following is simply invalid:
p = (10 + 20)
Given that, to quote: "Pointers and integers are not interchangeable. Zero is the only exception."
I interpret this to mean that *(a+i) is not performing straight forward integer arithmetic.
I believe this behaviour is determined by the existence of a pointer in the expression.
And to quote K&R again, and other answers provided to my question, the exact behaviour of arithmetic of arithmetic involving:
one pointer with
one or more integers
for (p + n) is defined like so: "n is scaled according to the size of the objects p points to, which is determined by the declaration of p".
I realised what caused me to be so confused: I have in the past been able to use printf() to output the actual address value of a pointer. I believe this is "undefined behaviour" which the compiler I was using happened to handle by treating the pointer as an integer.
Similarly, given the above two numbered bullet points, and the definition that uses them, I gather that adding two pointers together (of the same type) results in undefined behaviour, and more certainly, adding two pointers of different types.
To get the nth byte of an integer, see this question.
K&R later adds that the following are legal pointer operations:
Assigning one pointer to another (of the same type)
Adding or subtracting a pointer and an integer
Subtracting one pointer from another (to the same array)
Comparing pointers (to the same array)
Assigning / comparing to 0
All other pointer arithmetic is illegal.