Does an Array variable point to itself? - c++

I tried some code to check the behavior of array and pointers. Its as follows.
#include <stdio.h>
main(){
int s[]={1,2};
int *b=s;
printf("%d, %d, %d\n", s, &s, *s);
printf("%d, %d, %d\n", b ,&b, *b);
}
Initially I thought of pointers and array to be same BUT...
To my surprise the value of 's' and '&s' are SAME unlike 'b'. Does that mean an Array variable "points to itself?"
I am also now confused with what actually is a variable "name"? How its binding takes place with a location in memory? I am just unable to visualize things that go on there!
And where in memory (RAM) is all the information stored at run time?

OK, let say the following is how the memory looks when you execute
int s[]={1,2};
int *b=s;
s[]
+-----+-----+
| 1 | 2 |
+-----+-----+
100 104
^
|
| int *b = &s
+-----+
| 100 |
+-----+
200
s is an array. What that means is, it is a contiguous memory location which is associated with a variable s and each element is accessed by offsetting the array variable name.
So when you use s it actually boils down to the address of the array (which is 100 in this case). And when you do *s, it boils down to *(s+0) which is equivalent of s[0] and so *s represents the contents stored in the zeroth location (in this case s[0] is 1). When do do an &s, this will print the address of the s (which is100` in this case).
Note that, here s and &s represents an address; *s and s[x] represents an integer.
The same applies to the pointer. So, b prints the content it has, which is the address of s (which is 100 in this case). &b prints the address of b, which is 200 in this case. And, *b prints the content of the first element of the array s which is 1.
I have modified you program to make it print the address.
#include <stdio.h>
int main(void)
{
int s[]={1,2};
int *b=s;
printf("%p, %p, %d\n", (void *)s, (void *)&s, *s);
printf("%p, %p, %d\n", (void *)b, (void *)&b, *b);
return 0;
}
Output:
0xbfc4f3e4, 0xbfc4f3e4, 1
0xbfc4f3e4, 0xbfc4f3ec, 1
EDIT: %p expects void *. Added the same!

An array, when used as an argument to a function, decays into a pointer to its first element. Similarly, taking the address of an array results in a pointer to the location of the first element (but with a different type).
As for your second question, a variable name only exists at compile-time. It typically has no representation in memory at runtime.

Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced with an expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.
Assume the following code:
int arr[10];
foo(arr);
In the call to the function foo, the expression arr is converted from type "10-element array of int" to "pointer to int", and the address of the first element of arr is what actually gets passed to foo.
We would define foo as either
void foo(int a[]) {}
or
void foo(int *a) {}
In the context of a function parameter declaration, T a[] and T a[N] are identical to T *a; the parameter is a pointer type, not an array type. Note that this is only true for function parameter declarations.
As mentioned above, one exception to this rule is when the array expression is the operand of the unary & operator. If we change the call to foo to read
foo(&arr);
then the type of the expression &arr is "pointer to 10-element array of int", or int (*)[10], and the value of the expression is the address of a. For this, the definition of foo would be
void foo(int (*a)[10]) {}
In C, the address of the array and the address of the first element of the array are the same - thus both of the expressions arr and &arr have the same value, but their types are different. This matters for operations involving pointer arithmetic. For example, assume our code had been written
int arr[10];
foo(arr);
...
void foo(int *a)
{
...
a++;
...
}
On entry, a points to arr[0]. The expression a++ would advance the pointer to point to the next integer in the array (arr[1]).
Now assume the code had been written as
int arr[10];
foo(&arr);
...
void foo(int (*a)[10])
{
...
a++;
...
}
On entry, a still points to arr[0] (remember, the address of the array is the same as the address of the first element of the array), but this time the expression a++ will advance the pointer to point to the next 10-element array of integers; instead of advancing the pointer sizeof (int) bytes, we advance it sizeof (int[10]) bytes.
So this is why in your printf statement you see the same values for both s and &s. You should use the %p conversion specifier to print pointer values, and it expects the corresponding argument to be type void *, so change those printf statements to
printf("%p %p %d\n", (void *) s, (void *) &s, *s);
printf("%p %p %d\n", (void *) b, (void *) &b, *b);

A simple way to think about this is that an array as a pointer can't be changed by assignment, it is effectively a constant pointer to a known amount of memory.
To try that, use:
myptr = myarray;
Which is perfectly ok, and then try:
myarray = myptr;
Which is not.

Related

Why are the addresses of these two local variables the same? [duplicate]

This question already has answers here:
What is array to pointer decay?
(11 answers)
Closed last year.
I have defined a function here that accepts an array as a parameter
void print(char ch[]);
When I call the function and give it the array as an argument
int main(){
char ch[10];
print(ch);
}
And I print the addresses of these two variables in two different functions,
#include <stdio.h>
void print(char ch[]) {
printf("address of ch is %d\n",ch);
}
int main() {
char ch[10];
print(ch);
printf("address of ch is %d\n",ch);
return 0;
}
the address of the array in the main function must be different from the address of the array as a parameter in the function I defined, but it is the same. Why?
And whether the address of a variable can be negative?
Thanks for taking the time to read this question.
char ch[10];
This variable is an array. It implicitly converts to a pointer to first element. The value of the pointer is the address of the object that it points, and that address is the output that you see1.
void print(char ch[]) {
This parameter is a pointer. It may look like an array, but array parameters are adjusted to be pointers to the element of the array instead. When you output the value of a pointer, you see the address of the pointed object; not the address of the variable that stores the pointer.
Since the pointer that you passed as an argument points to the first element of the local array, the address that you see1 is the same.
The variables have different addresses, but the value of the parameter variable is the same as the address of the first element of the array variable.
1 Except, you used the wrong format specifier that doesn't match the type of the argument, so the behaviour of the program is actually undefined. Don't do this. If you absolutely must use printf, then you must use the %p format specifier and convert the argument to void*.
For starters to output a pointer you need to use the conversion specifier %p instead pf the conversion specifier %d. Otherwise the call of printf invokes undefined behavior.
printf("address of ch is %p\n", ( void * )ch);
Secondly within the function this call of printf does not output the address of the variable ch itself. It outputs the address of the first element of the array pointed to by the pointer expression ch. As the array is not moved within memory then you will get the same value of the address.
To output the address of the function parameter you need to write
void print(char ch[]) {
printf("address of ch is %p\n", ( void * )&ch);
}
Pay attention to that in this call
print(ch);
the array is implicitly converted to pointer to its first element. And the compiler adjusts the function parameter having an array type to pointer to the array element type
void print(char *ch) {
There is a difference between these two calls of printf in main where the source array is declared and within the function
printf("address of ch is %p\n", ( void * )ch);
printf("address of ch is %p\n", ( void * )&ch);
Within the function the first call outputs the address of the first element of the array pointed to by the pointer ch that is the address of the extent of memory occupied by the array.
The second call outputs the address of the local variable ch itself having the type char * (as pointed above).
In main these calls outputs the same value that is the address of the extent of memory occupied by the array. The first call outputs the address of the first element of the array and the second call outputs the address of the array as a whole object. The both values are the initial address of the extent of memory occupied by the array.
You're right, two different arrays can't have the same address.
char ch[] is not an array though. Attempting to use an array as a function parameter silently creates a pointer instead, so in this case it means char *ch. (But char ch[10]; in main is still an array, since it's not a parameter.)
ch (where ch is a char ch[] parameter) is not an address of ch. It's an address that ch points to. &ch would an address of ch itself, and it would have a different value.
But for char ch[10] in main, due to it being an array, ch and &ch have the same value (but different types: char * vs char (*)[10] (pointer to an array of 10 char)).
Why are the addresses of these two local variables the same?
Passing a C-style array to a function actually passes its pointer to that function, not the whole array. This void print(char ch[]); is the same as void print(char* ch); So both functions are printing the address of the same array in main function (char ch[10];).
If you want to pass a copy of an array to a function, you can use std::array as below:
#include <cstdio>
#include <array>
template<std::size_t N>
void print(std::array<char, N> ch) {
printf("address of ch is %d\n", ch.data());
}
int main() {
std::array<char, 10> ch;
print(ch);
printf("address of ch is %d\n", ch.data());
return 0;
}
Now the addresses won't be the same.
And whether the address of a variable can be negative?
Here:
printf("address of ch is %d\n",ch);
the above statement is interpreting ch (a pointer) as a decimal value (because of '%d'). That's why you're seeing a negative number. You need to use %p instead:
void print(char ch[]) {
printf("address of ch is %p\n", (void*) &ch);
}

Why in multi-dimentional array in C/C++ a[0] is same as a?

I have the following program
#include<stdio.h>
int main() {
int a[3][3]={{1,2,3},
{4,5,6},
{7,8,9}};
printf("%p\n",a);
printf("%p\n",a[0]);
printf("%p\n",*(a+0));
}
And it gives me the following output:
6356716
6356716
6356716
I was expecting that, given a base address such as 6356716 then *(6356716+0) would yield the value inside that location (i.e, 1).
So, if an array name is equivalent to a pointer to its first value like in above expression, printing 'a' should print the pointer to its first value i.e a[0](which itself decays to its 1st element at location 6356716). In that case, why does dereferencing not work here, and *(a+0) evaluates to
*(6356716+0)?
a is an array of 3 arrays of 3 int. When used in an expression other than as an operand of sizeof, unary &, or _Alignof, it is automatically converted to a pointer to its first argument, which is an array of 3 int. If you correctly print this pointer, it will show the address of that array of 3 int.
a[0] is the first element in a, so it is an array of 3 int. When used in an expression, with the same exceptions as above, it is automatically converted to a pointer to its first element, which is an int. If you correctly print this pointer, it will show the address of that int.
Since an array is simply a sequence of objects stored contiguously, an array starts at the same place that its first element does. Therefore, the results of printing a and a[0] show the same address.
*(a+0) is the same as a[0], so printing it has the same result.
You should not use %u to print address. Printing pointers with %u has undefined behavior. It might appear to work in your implementation in some circumstances, but it will break in other circumstances. To print an address, use %p with a pointer converted to void * or const void *:
printf("%p\n", (const void *) a);
printf("%p\n", (const void *) a[0]);
printf("%p\n", (const void *) *(a+0));
First thing you need to understand is that a 2D array is treated as an array of arrays and all the elements of 2D array are stored in continuous memory locations,Now the second thing to understand is that an array name actually gives the address of first element in it.So your first printf statement printf("%u\n",a);actually gives you the address of a[0],as a[0] is the first element in this 2D array.Now your second printf statement printf("%u\n",a[0]); gives you the address of a[0][0] , because a[0] is actually the name of first array in the 2D array.Now your last printf statement is printf("%u\n",*(a+0)); is actually the way a compiler internally treats array ,it is exactly same as the second one.As from the explanation it is clear that the three statements are referring to the same address but this does not mean that they are same thing ,the first statement has a different meaning as compared to second and third as explained above.Though the three statements are giving you the address of 1,which is the first element of the 2D array.
When used in
printf("%u\n", a);
printf("%u\n", a[0]);
a decays to the pointer to the first element of a and a[0] decays to the pointer to the first element of a[0]. Equivalently, you could use:
printf("%u\n", &a[0]);
printf("%u\n", &a[0][0]);
From a object type point of view, &a, &a[], and&a[0][0] are completely different pointer types. However, if you look at the memory layout of a 2D array, you will realize that, from a purely numerical point of view, &a == &a[] == &a[0][0].
Also, "%u" is not the correct format for printing pointers. You should use "%p".
printf("%p\n", a);
printf("%p\n", a[0]);

What is exactly a C array? [duplicate]

Is an array's name a pointer in C?
If not, what is the difference between an array's name and a pointer variable?
An array is an array and a pointer is a pointer, but in most cases array names are converted to pointers. A term often used is that they decay to pointers.
Here is an array:
int a[7];
a contains space for seven integers, and you can put a value in one of them with an assignment, like this:
a[3] = 9;
Here is a pointer:
int *p;
p doesn't contain any spaces for integers, but it can point to a space for an integer. We can, for example, set it to point to one of the places in the array a, such as the first one:
p = &a[0];
What can be confusing is that you can also write this:
p = a;
This does not copy the contents of the array a into the pointer p (whatever that would mean). Instead, the array name a is converted to a pointer to its first element. So that assignment does the same as the previous one.
Now you can use p in a similar way to an array:
p[3] = 17;
The reason that this works is that the array dereferencing operator in C, [ ], is defined in terms of pointers. x[y] means: start with the pointer x, step y elements forward after what the pointer points to, and then take whatever is there. Using pointer arithmetic syntax, x[y] can also be written as *(x+y).
For this to work with a normal array, such as our a, the name a in a[3] must first be converted to a pointer (to the first element in a). Then we step 3 elements forward, and take whatever is there. In other words: take the element at position 3 in the array. (Which is the fourth element in the array, since the first one is numbered 0.)
So, in summary, array names in a C program are (in most cases) converted to pointers. One exception is when we use the sizeof operator on an array. If a was converted to a pointer in this context, sizeof a would give the size of a pointer and not of the actual array, which would be rather useless, so in that case a means the array itself.
When an array is used as a value, its name represents the address of the first element.
When an array is not used as a value its name represents the whole array.
int arr[7];
/* arr used as value */
foo(arr);
int x = *(arr + 1); /* same as arr[1] */
/* arr not used as value */
size_t bytes = sizeof arr;
void *q = &arr; /* void pointers are compatible with pointers to any object */
If an expression of array type (such as the array name) appears in a larger expression and it isn't the operand of either the & or sizeof operators, then the type of the array expression is converted from "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element in the array.
In short, the array name is not a pointer, but in most contexts it is treated as though it were a pointer.
Edit
Answering the question in the comment:
If I use sizeof, do i count the size of only the elements of the array? Then the array “head” also takes up space with the information about length and a pointer (and this means that it takes more space, than a normal pointer would)?
When you create an array, the only space that's allocated is the space for the elements themselves; no storage is materialized for a separate pointer or any metadata. Given
char a[10];
what you get in memory is
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[9]
+---+
The expression a refers to the entire array, but there's no object a separate from the array elements themselves. Thus, sizeof a gives you the size (in bytes) of the entire array. The expression &a gives you the address of the array, which is the same as the address of the first element. The difference between &a and &a[0] is the type of the result1 - char (*)[10] in the first case and char * in the second.
Where things get weird is when you want to access individual elements - the expression a[i] is defined as the result of *(a + i) - given an address value a, offset i elements (not bytes) from that address and dereference the result.
The problem is that a isn't a pointer or an address - it's the entire array object. Thus, the rule in C that whenever the compiler sees an expression of array type (such as a, which has type char [10]) and that expression isn't the operand of the sizeof or unary & operators, the type of that expression is converted ("decays") to a pointer type (char *), and the value of the expression is the address of the first element of the array. Therefore, the expression a has the same type and value as the expression &a[0] (and by extension, the expression *a has the same type and value as the expression a[0]).
C was derived from an earlier language called B, and in B a was a separate pointer object from the array elements a[0], a[1], etc. Ritchie wanted to keep B's array semantics, but he didn't want to mess with storing the separate pointer object. So he got rid of it. Instead, the compiler will convert array expressions to pointer expressions during translation as necessary.
Remember that I said arrays don't store any metadata about their size. As soon as that array expression "decays" to a pointer, all you have is a pointer to a single element. That element may be the first of a sequence of elements, or it may be a single object. There's no way to know based on the pointer itself.
When you pass an array expression to a function, all the function receives is a pointer to the first element - it has no idea how big the array is (this is why the gets function was such a menace and was eventually removed from the library). For the function to know how many elements the array has, you must either use a sentinel value (such as the 0 terminator in C strings) or you must pass the number of elements as a separate parameter.
Which *may* affect how the address value is interpreted - depends on the machine.
An array declared like this
int a[10];
allocates memory for 10 ints. You can't modify a but you can do pointer arithmetic with a.
A pointer like this allocates memory for just the pointer p:
int *p;
It doesn't allocate any ints. You can modify it:
p = a;
and use array subscripts as you can with a:
p[2] = 5;
a[2] = 5; // same
*(p+2) = 5; // same effect
*(a+2) = 5; // same effect
The array name by itself yields a memory location, so you can treat the array name like a pointer:
int a[7];
a[0] = 1976;
a[1] = 1984;
printf("memory location of a: %p", a);
printf("value at memory location %p is %d", a, *a);
And other nifty stuff you can do to pointer (e.g. adding/substracting an offset), you can also do to an array:
printf("value at memory location %p is %d", a + 1, *(a + 1));
Language-wise, if C didn't expose the array as just some sort of "pointer"(pedantically it's just a memory location. It cannot point to arbitrary location in memory, nor can be controlled by the programmer). We always need to code this:
printf("value at memory location %p is %d", &a[1], a[1]);
I think this example sheds some light on the issue:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
int **b = &a;
printf("a == &a: %d\n", a == b);
return 0;
}
It compiles fine (with 2 warnings) in gcc 4.9.2, and prints the following:
a == &a: 1
oops :-)
So, the conclusion is no, the array is not a pointer, it is not stored in memory (not even read-only one) as a pointer, even though it looks like it is, since you can obtain its address with the & operator. But - oops - that operator does not work :-)), either way, you've been warned:
p.c: In function ‘main’:
pp.c:6:12: warning: initialization from incompatible pointer type
int **b = &a;
^
p.c:8:28: warning: comparison of distinct pointer types lacks a cast
printf("a == &a: %d\n", a == b);
C++ refuses any such attempts with errors in compile-time.
Edit:
This is what I meant to demonstrate:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
void *c = a;
void *b = &a;
void *d = &c;
printf("a == &a: %d\n", a == b);
printf("c == &c: %d\n", c == d);
return 0;
}
Even though c and a "point" to the same memory, you can obtain address of the c pointer, but you cannot obtain the address of the a pointer.
The following example provides a concrete difference between an array name and a pointer. Let say that you want to represent a 1D line with some given maximum dimension, you could do it either with an array or a pointer:
typedef struct {
int length;
int line_as_array[1000];
int* line_as_pointer;
} Line;
Now let's look at the behavior of the following code:
void do_something_with_line(Line line) {
line.line_as_pointer[0] = 0;
line.line_as_array[0] = 0;
}
void main() {
Line my_line;
my_line.length = 20;
my_line.line_as_pointer = (int*) calloc(my_line.length, sizeof(int));
my_line.line_as_pointer[0] = 10;
my_line.line_as_array[0] = 10;
do_something_with_line(my_line);
printf("%d %d\n", my_line.line_as_pointer[0], my_line.line_as_array[0]);
};
This code will output:
0 10
That is because in the function call to do_something_with_line the object was copied so:
The pointer line_as_pointer still contains the same address it was pointing to
The array line_as_array was copied to a new address which does not outlive the scope of the function
So while arrays are not given by values when you directly input them to functions, when you encapsulate them in structs they are given by value (i.e. copied) which outlines here a major difference in behavior compared to the implementation using pointers.
The array name behaves like a pointer and points to the first element of the array. Example:
int a[]={1,2,3};
printf("%p\n",a); //result is similar to 0x7fff6fe40bc0
printf("%p\n",&a[0]); //result is similar to 0x7fff6fe40bc0
Both the print statements will give exactly same output for a machine. In my system it gave:
0x7fff6fe40bc0

What's the difference between int** as a parameter and int** in main function? [duplicate]

Is an array's name a pointer in C?
If not, what is the difference between an array's name and a pointer variable?
An array is an array and a pointer is a pointer, but in most cases array names are converted to pointers. A term often used is that they decay to pointers.
Here is an array:
int a[7];
a contains space for seven integers, and you can put a value in one of them with an assignment, like this:
a[3] = 9;
Here is a pointer:
int *p;
p doesn't contain any spaces for integers, but it can point to a space for an integer. We can, for example, set it to point to one of the places in the array a, such as the first one:
p = &a[0];
What can be confusing is that you can also write this:
p = a;
This does not copy the contents of the array a into the pointer p (whatever that would mean). Instead, the array name a is converted to a pointer to its first element. So that assignment does the same as the previous one.
Now you can use p in a similar way to an array:
p[3] = 17;
The reason that this works is that the array dereferencing operator in C, [ ], is defined in terms of pointers. x[y] means: start with the pointer x, step y elements forward after what the pointer points to, and then take whatever is there. Using pointer arithmetic syntax, x[y] can also be written as *(x+y).
For this to work with a normal array, such as our a, the name a in a[3] must first be converted to a pointer (to the first element in a). Then we step 3 elements forward, and take whatever is there. In other words: take the element at position 3 in the array. (Which is the fourth element in the array, since the first one is numbered 0.)
So, in summary, array names in a C program are (in most cases) converted to pointers. One exception is when we use the sizeof operator on an array. If a was converted to a pointer in this context, sizeof a would give the size of a pointer and not of the actual array, which would be rather useless, so in that case a means the array itself.
When an array is used as a value, its name represents the address of the first element.
When an array is not used as a value its name represents the whole array.
int arr[7];
/* arr used as value */
foo(arr);
int x = *(arr + 1); /* same as arr[1] */
/* arr not used as value */
size_t bytes = sizeof arr;
void *q = &arr; /* void pointers are compatible with pointers to any object */
If an expression of array type (such as the array name) appears in a larger expression and it isn't the operand of either the & or sizeof operators, then the type of the array expression is converted from "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element in the array.
In short, the array name is not a pointer, but in most contexts it is treated as though it were a pointer.
Edit
Answering the question in the comment:
If I use sizeof, do i count the size of only the elements of the array? Then the array “head” also takes up space with the information about length and a pointer (and this means that it takes more space, than a normal pointer would)?
When you create an array, the only space that's allocated is the space for the elements themselves; no storage is materialized for a separate pointer or any metadata. Given
char a[10];
what you get in memory is
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[9]
+---+
The expression a refers to the entire array, but there's no object a separate from the array elements themselves. Thus, sizeof a gives you the size (in bytes) of the entire array. The expression &a gives you the address of the array, which is the same as the address of the first element. The difference between &a and &a[0] is the type of the result1 - char (*)[10] in the first case and char * in the second.
Where things get weird is when you want to access individual elements - the expression a[i] is defined as the result of *(a + i) - given an address value a, offset i elements (not bytes) from that address and dereference the result.
The problem is that a isn't a pointer or an address - it's the entire array object. Thus, the rule in C that whenever the compiler sees an expression of array type (such as a, which has type char [10]) and that expression isn't the operand of the sizeof or unary & operators, the type of that expression is converted ("decays") to a pointer type (char *), and the value of the expression is the address of the first element of the array. Therefore, the expression a has the same type and value as the expression &a[0] (and by extension, the expression *a has the same type and value as the expression a[0]).
C was derived from an earlier language called B, and in B a was a separate pointer object from the array elements a[0], a[1], etc. Ritchie wanted to keep B's array semantics, but he didn't want to mess with storing the separate pointer object. So he got rid of it. Instead, the compiler will convert array expressions to pointer expressions during translation as necessary.
Remember that I said arrays don't store any metadata about their size. As soon as that array expression "decays" to a pointer, all you have is a pointer to a single element. That element may be the first of a sequence of elements, or it may be a single object. There's no way to know based on the pointer itself.
When you pass an array expression to a function, all the function receives is a pointer to the first element - it has no idea how big the array is (this is why the gets function was such a menace and was eventually removed from the library). For the function to know how many elements the array has, you must either use a sentinel value (such as the 0 terminator in C strings) or you must pass the number of elements as a separate parameter.
Which *may* affect how the address value is interpreted - depends on the machine.
An array declared like this
int a[10];
allocates memory for 10 ints. You can't modify a but you can do pointer arithmetic with a.
A pointer like this allocates memory for just the pointer p:
int *p;
It doesn't allocate any ints. You can modify it:
p = a;
and use array subscripts as you can with a:
p[2] = 5;
a[2] = 5; // same
*(p+2) = 5; // same effect
*(a+2) = 5; // same effect
The array name by itself yields a memory location, so you can treat the array name like a pointer:
int a[7];
a[0] = 1976;
a[1] = 1984;
printf("memory location of a: %p", a);
printf("value at memory location %p is %d", a, *a);
And other nifty stuff you can do to pointer (e.g. adding/substracting an offset), you can also do to an array:
printf("value at memory location %p is %d", a + 1, *(a + 1));
Language-wise, if C didn't expose the array as just some sort of "pointer"(pedantically it's just a memory location. It cannot point to arbitrary location in memory, nor can be controlled by the programmer). We always need to code this:
printf("value at memory location %p is %d", &a[1], a[1]);
I think this example sheds some light on the issue:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
int **b = &a;
printf("a == &a: %d\n", a == b);
return 0;
}
It compiles fine (with 2 warnings) in gcc 4.9.2, and prints the following:
a == &a: 1
oops :-)
So, the conclusion is no, the array is not a pointer, it is not stored in memory (not even read-only one) as a pointer, even though it looks like it is, since you can obtain its address with the & operator. But - oops - that operator does not work :-)), either way, you've been warned:
p.c: In function ‘main’:
pp.c:6:12: warning: initialization from incompatible pointer type
int **b = &a;
^
p.c:8:28: warning: comparison of distinct pointer types lacks a cast
printf("a == &a: %d\n", a == b);
C++ refuses any such attempts with errors in compile-time.
Edit:
This is what I meant to demonstrate:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
void *c = a;
void *b = &a;
void *d = &c;
printf("a == &a: %d\n", a == b);
printf("c == &c: %d\n", c == d);
return 0;
}
Even though c and a "point" to the same memory, you can obtain address of the c pointer, but you cannot obtain the address of the a pointer.
The following example provides a concrete difference between an array name and a pointer. Let say that you want to represent a 1D line with some given maximum dimension, you could do it either with an array or a pointer:
typedef struct {
int length;
int line_as_array[1000];
int* line_as_pointer;
} Line;
Now let's look at the behavior of the following code:
void do_something_with_line(Line line) {
line.line_as_pointer[0] = 0;
line.line_as_array[0] = 0;
}
void main() {
Line my_line;
my_line.length = 20;
my_line.line_as_pointer = (int*) calloc(my_line.length, sizeof(int));
my_line.line_as_pointer[0] = 10;
my_line.line_as_array[0] = 10;
do_something_with_line(my_line);
printf("%d %d\n", my_line.line_as_pointer[0], my_line.line_as_array[0]);
};
This code will output:
0 10
That is because in the function call to do_something_with_line the object was copied so:
The pointer line_as_pointer still contains the same address it was pointing to
The array line_as_array was copied to a new address which does not outlive the scope of the function
So while arrays are not given by values when you directly input them to functions, when you encapsulate them in structs they are given by value (i.e. copied) which outlines here a major difference in behavior compared to the implementation using pointers.
The array name behaves like a pointer and points to the first element of the array. Example:
int a[]={1,2,3};
printf("%p\n",a); //result is similar to 0x7fff6fe40bc0
printf("%p\n",&a[0]); //result is similar to 0x7fff6fe40bc0
Both the print statements will give exactly same output for a machine. In my system it gave:
0x7fff6fe40bc0

Difference between char[] and char* in function call

I have found myself unable to explain why the following piece of code works. Needless to say, I am quite new to C++...
#include <cstdio>
void foo(char* p)
{
p[0] = 'y';
}
int main()
{
char a[1];
a[0] = 'x';
printf("a[0] = %c\n", a[0]);
foo(a);
printf("a[0] = %c\n", a[0]);
return 0;
}
This program outputs
a[0] = x
a[0] = y
What intrigues me us that I am not passing a pointer, but an array, to foo. So how can foo change the value of the array a? Does this apply only to arrays of char?
The answer to Difference between char and char[1], confirms my observation, but it does not go into detail about why this is the case.
Thanks!
When you're passing an array to a function it decays to a pointer to the first element.
The following are completely equivalent:
void foo(char* p);
void foo(char p[]);
void foo(char p[42]); /* Or any other number. */
Does this apply only to arrays of char?
It applies to any array. I recommend the aryptr section of the C FAQ.
In C, arrays, in most contexts (*), decay into a pointer to their first element.
In your case, the array a decays into a pointer to a[0].
The array int arr[12][23], when used just by its identifier, decays to a pointer to its first element, namely arr[0], which is of type int (*)[23] (pointer to array of 23 ints).
(*) Arrays do not decay when used as the argument to the sizeof operator, or when used as argument to the & operator or when used as initializer (a string literal) for a character array.
When You say
char a[5];
the compiler allocates 5 sequential blocks of memory, and the address of the first block is assigned to a. So by definition name of the array (a in our case) is just a pointer to a memory location.
Now when we say a[0], compiler manipulates it as *(a+0*sizeof(array datatype i.e. char, int etc.)), symbolically a[i] is represented as *(a+i*sizeof(array datatype i.e. char, int etc.))
As far as function parameter passing is concerned When we pass an array to a function basically it is just the address of the first element which is passed. For more details regarding this plz follow this link or read the #cnicutar's answer (as he has already posted a correct answer there is no point repeating that again)...
You can try this to convince yourself how this works.
int a[8], *p;
p = a;
printf("%p, %p, %p\n", a, &a[0], p);
An array is nothing more than a pointer (to the first element), at least for argument passing sake.
The three prototypes here are equivalent:
void foo(char *p);
void foo(char p[]);
void foo(char p[42]);
C says a declaration of parameter of type array of T is adjusted to a declaration of type pointer to T.
Array name points to the address of the first element of the array. Please refer: Is an array name a pointer?