Swap function for Array - c++

Information that we have:
1) defining an array a[1000] , a is the pointer address.
2)
void swap(int &c, int &b)
{
c=c+b;
b=c-b;
c=c-b;
}
// this is a method of swapping two variables without using temp variable.
// We use call by reference for the swap to actually take place in memory.
Now , when i call this function for a's two entries say a[i],a[j] ...what happens ?? Does the function receive the address of the two cells of the array due to some internal construct of C/C++ or does it receive the address of the pointers pointing at a[i] and a[j] ?

a[i] evaluates to a reference to the ith element. It is the equivalent of *(a+i), where a+i is a pointer to the ith element.
How references work internally is implementation defined (you shouldn't care), but most(all) compilers use pointers internally. In this case they would be pointers to the two elements in the array.

I'd say that behind the scene it would receive pointers to a[i] and a[j].
Running g++ -S on the following two programs produces identical results:
#include<iostream>
extern "C" void swap(int&c,int&b){
c=c+b;
b=c-b;
c=c-b;
}
int main(){
int*a=new int[1000];
a[10]=10;
a[42]=42;
swap(a[10],a[42]);
std::cout << a[10] << " " << a[42] << std::endl;
delete[] a;
return 0;
}
and
#include<iostream>
extern "C" void swap(int*c,int*b){
*c=*c+*b;
*b=*c-*b;
*c=*c-*b;
}
int main(){
int*a=new int[1000];
a[10]=10;
a[42]=42;
swap(a+10,a+42);
std::cout << a[10] << " " << a[42] << std::endl;
delete[] a;
return 0;
}
where I used extern "C" to be able to diff the outputs, otherwise the mangling differs.
Side note, when you write e.g. a+42 the compiler will calculate the address as a+sizeof(int)*42, taking into account that a is a pointer to int. This particular example shows up as an addl $168, %eax in the generated assembly source.

A) C and C++ are two different languages. Given your swap(int &c, int &b) method definition, it's C++
B) Because it's C++ and you're passing references, you get a reference to the array element (which in memory is located at a + i)
If this were C you would have defined your function as swap(int *c, int *d) and you'd be passing the pointer a + i because array degrade to pointers automatically.

defining an array a[1000] , a is the pointer address.
No it isn't. a is an array. In many cases it decays to a pointer to the first element, but it is not the address of a pointer (unless you made an array of pointers, of course).

First of all, your swap function is a bad idea as the value of the sum might overflow. Just use a temp variable.
When you call swap(a[i], a[j]) the arguments to the function are two pointers to the memory locations a[i] and a[j]. The pointers contain the addresses of the two ints. The function swap() will have no concept of the two ints being in the same array.
Declaring c and d as references is similar to passing a pointer, however, you can only work with the values stored in this memory location (equivalent to dereferencing the pointer) but not change the address the pointer points to.

The idea of swapping two numbers without temp works well only if sum of numbers is in the range of value ;a int can hold.(typically power(2,sizeof(int))).or else overflow will occur.
Coming to the question,
int *a=new int;
a[1000];// if i have understood your question then....
As mentioned by you here A is a pointer and A[i] is array formed with A as base address.
In c when you say p[i] internally it get converted as *(p+i) where p is base address.similarly when you pass by reference address of value is passed.
Note :References are implicitly constant ,references must be given value upon declaration.
References acts like a const pointer that is implicitly de-referenced.It is safe to pass references than that of pointers as using pointer may lead to segfaults.(where there is no dynamic allocation of memory)

a[i] represents the value so &a[i] = a + i will be passed (internally). Likewise for a[j].

Related

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

What exactly is the purpose of the (asterisk) in pointers?

I'm new to programming and I'm trying to wrap my head around the idea of 'pointers'.
int main()
{
int x = 5;
int *pointerToInteger = & x;
cout<<pointerToInteger;
}
Why is it that when I cout << pointerToInteger; the output is a hexdecimal value, BUT when I use cout << *pointerToInteger; the output is 5 ( x=5).
* has different meaning depending on the context.
Declaration of a pointer
int* ap; // It defines ap to be a pointer to an int.
void foo(int* p); // Declares function foo.
// foo expects a pointer to an int as an argument.
Dereference a pointer in an expression.
int i = 0;
int* ap = &i; // ap points to i
*ap = 10; // Indirectly sets the value of i to 10
A multiplication operator.
int i = 10*20; // Needs no explanation.
One way to look at it, is that the variable in your source/code, say
int a=0;
Makes the 'int a' refer to a value in memory, 0. If we make a new variable, this time a (potentially smaller) "int pointer", int *, and have it point to the &a (address of a)
int*p_a=&a; //(`p_a` meaning pointer to `a` see Hungarian notation)
Hungarian notation wiki
we get p_a that points to what the value &a is. Your talking about what is at the address of a now tho, and the *p_a is a pointer to whatever is at the &a (address of a).
This has uses when you want to modify a value in memory, without creating a duplicate container.
p_a itself has a footprint in memory however (potentially smaller than a itself) and when you cout<<p_a<<endl; you will write whatever the pointer address is, not whats there. *p_a however will be &a.
p_a is normally smaller than a itself, since its just a pointer to memory and not the value itself. Does that make sense? A vector of pointers will be easier to manage than a vector of values, but they will do the same thing in many regards.
If you declare a variable of some type, then you can also declare another variable pointing to it.
For example:
int a;
int* b = &a;
So in essence, for each basic type, we also have a corresponding pointer type.
For example: short and short*.
There are two ways to "look at" variable b (that's what probably confuses most beginners):
You can consider b as a variable of type int*.
You can consider *b as a variable of type int.
Hence, some people would declare int* b, whereas others would declare int *b.
But the fact of the matter is that these two declarations are identical (the spaces are meaningless).
You can use either b as a pointer to an integer value, or *b as the actual pointed integer value.
You can get (read) the pointed value: int c = *b.
And you can set (write) the pointed value: *b = 5.
A pointer can point to any memory address, and not only to the address of some variable that you have previously declared. However, you must be careful when using pointers in order to get or set the value located at the pointed memory address.
For example:
int* a = (int*)0x8000000;
Here, we have variable a pointing to memory address 0x8000000.
If this memory address is not mapped within the memory space of your program, then any read or write operation using *a will most likely cause your program to crash, due to a memory access violation.
You can safely change the value of a, but you should be very careful changing the value of *a.
yes the asterisk * have different meanings while declaring a pointer variable and while accessing data through pointer variable. for e.g
int input = 7;
int *i_ptr = &input;/*Here * indicates that i_ptr is a pointer variable
Also address is assigned to i_ptr, not to *iptr*/
cout<<*i_ptr;/* now this * is fetch the data from assigned address */
cout<<i_ptr;/*it prints address */
for e.g if you declare like int *ptr = 7; its wrong(not an error) as pointers ptr expects valid address but you provided constant(7). upto declaration it's okay but when you go for dereferencing it like *ptr it gives problem because it doesn't know what is that data/value at 7 location. So Its always advisable to assign pointers variable with valid addresses. for e.g
int input = 7;
int *i_ptr = &input;
cout<<*i_ptr;
for example
char *ptr = "Hello"; => here * is just to inform the compiler that ptr is a pointer variable not normal one &
Hello is a char array i.e valid address, so this syntax is okay. Now you can do
if(*ptr == 'H') {
/*....*/
}
else {
/*.... */
}

Where's the pointer to an array stored in a struct?

I have a struct that looks like this.
struct puzzle {
int d[16];
};
I heard that arrays and pointers are the same in C/C++, so I thought that the struct would store a pointer, and the pointer points to an int array. However, I did simple experiments using a debugger to see how exactly is it stored, and I found out that the array is directly stored in the struct.
Why isn't the array pointer stored in the struct?
Where is the pointer stored at?
I heard that arrays and pointers are the same in C/C++
No! They're very different. An array expression decays into a pointer in many instances, but that's about it. Beyond that arrays and pointers are very different creatures. Understand more about the decaying nature of arrays to avoid confusions like this: What is array decaying?
Why isn't the array pointer stored in the struct? Where is the pointer stored at?
The array is the member of the struct and it's stored as expected. The decayed pointer is obtained implicitly, there's nothing to store here.
struct puzzle s;
int *p = s.d; /* p is now pointing to s.d[0] */
Here s.d gets implicitly converted to int*. Where this decay happens and where it doesn't depends on the language in question. In C++ there're more instances than in C. This is another reason why not to tag a question both C and C++.
I heard that arrays and pointers are the same in C/C++!!!!!
Arrays
An array is a fixed-length collection of objects, which are stored sequentially in memory.
Pointers
A pointer is a value that refers to another object (or function). You might say it contains the object's address.
Arrays decay to pointer (implicit pointer conversion ) when they are passed to functions.
Why isn't the array pointer stored in the struct?
Just because the postman know the address of your house, will you let him stay with you?? Only the members of your family can stay, right? Same in your case, the array is the member of struct.
Arrays and pointers are different things in C.
In many cases array variables can be treated as pointers, e.g. when passed as arguments to a function taking a pointer:
void f(int *p);
main() {
int a[3] = {1, 2, 3};
f(a);
}
But arrays themselves are not pointers at all, they are continuous pieces of memory allocated somewhere (in your case inside a struct).
Arrays and pointers are different types. An array is a named or unnamed extent of memory allocated for its elements.
A pointer is an object that stores an address.
For example if you execute this statement
std::cout << sizeof( puzzle ) << std::endl;
for a structure declared like this
struct puzzle {
int d[16];
};
then the output will be at least not less than the value 16 * sizeof( int ).
If you will execute the same statement
std::cout << sizeof( puzzle ) << std::endl;
for a dtructure declared like this
struct puzzle {
int *d;
};
then the output will be at least equal to the value sizeof( int * ).
Arrays are implicitly converted to pointers to their first elements when they are used in expressions.
For example
int a[16];
int *p = a;
Here in the second declaration array a used as initializer is converted to pointer to its first element.
There is no difference between using an array or a pointer with the subscript operator like
a[i]
or
p[i]
because in the both cases this expression is evaluated like
*( a + i )
or
*( p + i )
that is again the array is converted to pointer to its first element and there is used the pointer arithmetic in the expression.
Arrays have sequential access.a[0] location is =100 means ,a[1] would be in 101, a[2] in 102.
Pointers are not sequential they are randomly stored based on the address.

Why can't we pass arrays to function by value?

Apparently, we can pass complex class instances to functions, but why can't we pass arrays to functions?
The origin is historical. The problem is that the rule "arrays decay into pointers, when passed to a function" is simple.
Copying arrays would be kind of complicated and not very clear, since the behavior would change for different parameters and different function declarations.
Note that you can still do an indirect pass by value:
struct A { int arr[2]; };
void func(struct A);
Here's another perspective: There isn't a single type "array" in C. Rather, T[N] is a a different type for every N. So T[1], T[2], etc., are all different types.
In C there's no function overloading, and so the only sensible thing you could have allowed would be a function that takes (or returns) a single type of array:
void foo(int a[3]); // hypothetical
Presumably, that was just considered far less useful than the actual decision to make all arrays decay into a pointer to the first element and require the user to communicate the size by other means. After all, the above could be rewritten as:
void foo(int * a)
{
static const unsigned int N = 3;
/* ... */
}
So there's no loss of expressive power, but a huge gain in generality.
Note that this isn't any different in C++, but template-driven code generation allows you to write a templated function foo(T (&a)[N]), where N is deduced for you -- but this just means that you can create a whole family of distinct, different functions, one for each value of N.
As an extreme case, imagine that you would need two functions print6(const char[6]) and print12(const char[12]) to say print6("Hello") and print12("Hello World") if you didn't want to decay arrays to pointers, or otherwise you'd have to add an explicit conversion, print_p((const char*)"Hello World").
Answering a very old question, as Question is market with C++ just adding for completion purposes, we can use std::array and pass arrays to functions by value or by reference which gives protection against accessing out of bound indexes:
below is sample:
#include <iostream>
#include <array>
//pass array by reference
template<size_t N>
void fill_array(std::array<int, N>& arr){
for(int idx = 0; idx < arr.size(); ++idx)
arr[idx] = idx*idx;
}
//pass array by value
template<size_t N>
void print_array(std::array<int, N> arr){
for(int idx = 0; idx < arr.size(); ++idx)
std::cout << arr[idx] << std::endl;
}
int main()
{
std::array<int, 5> arr;
fill_array(arr);
print_array(arr);
//use different size
std::array<int, 10> arr2;
fill_array(arr2);
print_array(arr2);
}
The reason you can't pass an array by value is because there is no specific way to track an array's size such that the function invocation logic would know how much memory to allocate and what to copy. You can pass a class instance because classes have constructors. Arrays do not.
Summery:
Passing the Address of the array's first element &a = a = &(a[0])
New Pointer (new pointer, new address, 4 bytes, in the memory)
Points to the same memory location, in different type.
Example 1:
void by_value(bool* arr) // pointer_value passed by value
{
arr[1] = true;
arr = NULL; // temporary pointer that points to original array
}
int main()
{
bool a[3] = {};
cout << a[1] << endl; // 0
by_value(a);
cout << a[1] << endl; // 1 !!!
}
Addresses:
[main]
a = 0046FB18 // **Original**
&a = 0046FB18 // **Original**
[func]
arr = 0046FB18 // **Original**
&arr = 0046FA44 // TempPTR
[func]
arr = NULL
&arr = 0046FA44 // TempPTR
Example 2:
void by_value(bool* arr)
{
cout << &arr << arr; // &arr != arr
}
int main()
{
bool a[3] = {};
cout << &a << a; // &a == a == &a[0]
by_value(arr);
}
Addresses
Prints:
[main] 0046FB18 = 0046FB18
[func] 0046FA44 != 0046FB18
Please Note:
&(required-lvalue): lvalue -to-> rvalue
Array Decay: new pointer (temporary) points to (by value) array address
readmore:
Rvalue
Array Decay
It was done that way in order to preserve syntactical and semantic compatibility with B language, in which arrays were implemented as physical pointers.
A direct answer to this question is given in Dennis Ritchie's "The Development of the C Language", see the "Critique" section. It says
For example, the empty square brackets in the function declaration
int f(a) int a[]; { ... }
are a living fossil, a remnant of NB's way of declaring a pointer; a is, in this special case only, interpreted in C as a pointer. The notation survived in part for the sake of compatibility, in part under the rationalization that it would allow programmers to communicate to their readers an intent to pass f a pointer generated from an array, rather than a reference to a single integer. Unfortunately, it serves as much to confuse the learner as to alert the reader.
This should be taken in the context of the previous part of the article, especially "Embryonic C", which explains how introduction of struct types in C resulted in rejection of B- and BCPL-style approach to implementing arrays (i.e. as ordinary pointers). C switched to non-pointer array implementation, keeping that legacy B-style semantics in function parameter lists only.
So, the current variant of array parameter behavior is a result of a compromise: one the one hand, we had to have copyable arrays in structs, on the other hand, we wanted to preserve semantic compatibility with functions written in B, where arrays are always passed "by pointer".
The equivalent of that would be to first make a copy of the array and then pass it to the function (which can be highly inefficient for large arrays).
Other than that I would say it's for historical reasons, i.e. one could not pass arrays by value in C.
My guess is that the reasoning behind NOT introducing passing arrays by value in C++ was that objects were thought to be moderately sized compared to arrays.
As pointed out by delnan, when using std::vector you can actually pass array-like objects to functions by value.
You are passing by value: the value of the pointer to the array. Remember that using square bracket notation in C is simply shorthand for de-referencing a pointer. ptr[2] means *(ptr+2).
Dropping the brackets gets you a pointer to the array, which can be passed by value to a function:
int x[2] = {1, 2};
int result;
result = DoSomething(x);
See the list of types in the ANSI C spec. Arrays are not primitive types, but constructed from a combination of pointers and operators. (It won't let me put another link, but the construction is described under "Array type derivation".)
actually, a pointer to the array is passed by value, using that pointer inside the called function will give you the feeling that the array is passed by reference which is wrong. try changing the value in the array pointer to point to another array in your function and you will find that the original array was not affected which means that the array is not passed by reference.