void swap(int a[], int size){
...............
}
int main(){
int x[4] = {4,5,3,12} ;
swap(x,4) ;
// print array here - some elements are swapped
}
So I'm not sure how it is possible for the swap-function to change the order of elements
since it is passed by value in void swap?
If I do something like this: void swap( int (&a)[], int size)
then the original array in my main function would get changed, but how does swap function swap elements, if it just copies the array, and hence should not make any effect on the array in main?
Arrays are not copied when passed as a function arguments. They are "decayed" (automatically converted) to pointers to appropriate first elements. So this code
void swap(int a[], int size) { ... }
is equivalent to
void swap(int* a, int size) { ... }
which should now explain the behavior observed.
(And if indeed you want to prevent that conversion, pass the array by reference).
In C and C++, when you pass an array to a function, you are actually only passing its address (yes, by value, but of course that doesn't change anything since an address passed by value or not always points to the same location).
In the function, whatever element of the array you access or change would be the original one.
So basically, your answer is that you got everything right and no need to do anything.
Example:
void swap(int a[], int size){
for (int i = 0; i < size/2; ++i)
{
a[i] ^= a[size-1-i]; // If you are interested
a[size-1-i] ^= a[i]; // try to understand
a[i] ^= a[size-1-i]; // how this works
}
}
int main(){
int x[4] = {4,5,3,12} ;
swap(x,4) ;
// print array here - some elements are swapped
}
The array is not passed by value, it decays into an int*. Check this code:
void swap(int a[], int size){
}
void swap(int* a, int size){
}
int main()
{
}
Now see what the compiler says:
$ g++ -Wall test.cpp
test.cpp: In function ‘void swap(int*, int)’:
test.cpp:4:6: error: redefinition of ‘void swap(int*, int)’
test.cpp:1:6: error: ‘void swap(int*, int)’ previously defined here
It works because you are not passing the array by value. Passing an array to a function is the same as passing a pointer to the first element in the array. Thus, you are not actually passing by value.
For this reason, I recommend using the more obvious notation:
void swap(int* a, int size)
You would use the double pointer:
void swap(int** a, int size)
or
void swap(int & a[], int size)
only if you want the function to change the memory address of the original array.
i.e. You reallocate the memory and want the caller to receive the new array. Of course, in this case you would probably cause a nasty leak.
If you want to enforce call by value behavior then make the argument const.
void swap(const int* a, int size)
This will prevent the method from being allowed to alter the array in any way. This is useful when you are passing a video buffer or something to a user but you do not want them to corrupt the data.
Related
I have a function which requires **double, while the pointer I defined is *double, how to send it to the function? Sample code is the following,
void eig(int n, double **A);
int main(){
int DIM=5;
double *HMAT = new double [DIM*DIM];
eig(DIM,HMAT);
delete [] HMAT;
}
void eig(int n, double **A) {}
Compilation complains
main.cc:8:15: error: cannot convert ‘double*’ to ‘double**’ for argument ‘2’ to ‘void eig(int, double**)’
I think the misunderstanding is that void eig(int n, double **A) does not denote a "pointer to a 2D-array" but a pointer to a pointer to a double value.
Depending on what you do with A in function eig, this can be meaningful or not: If eig is about allocating or reallocating a new array, then you'd use a double **A in order to pass back the newly allocated memory to the caller. However, if you just want to access the values of the array, it's sufficient to pass just a pointer to the array (not a pointer to a pointer). See the following code explaining the difference. Hope it helps.
void eig1(int n, double **A) {
*A = new double [n*n]; // OK; pass back the array by writing its starting address into the pointer to which A points.
}
void eig2(int n, double *A) {
A = new double [n*n]; // does not make sense; changes local variable `A` only; will result in a memory leak
}
void eig_populate(int n, double *A) {
for (int i=0;i<n;i++) {
A[i]=i; // OK; does not allocate a new array but accesses an existing one
}
}
int main(){
double *HMAT = nullptr;
eig2(5,HMAT); // will not change HMAT
eig1(5,&HMAT); // will change HMAT
eig_populate(5, HMAT);
}
You've misread the error message. Pay attention to line numbers: the problem isn't the call to eig, it's the assignment of a double** created by new *[DIM*DIM] to HMAT, whose type is double*. To fix that error, change the type of HMAT to double**.
I am trying to pass a multidimensional array to a function. When I try to compile I an getting an error saying
[Error] cannot convert 'int (*)[3]' to 'int (*)[2]' for argument '1' to 'void reve(int (*)[2], int)'
What is the problem ? What am I doing wrong? Following is the code I wrote.
#include <iostream>
using namespace std;
const int rows=2;
const int cols=2;
const int n = 3;
void reve(int arr[rows][cols],int n){
int br[3][3],i,j,k,l;
for(i=n-1,k=0;i>=0,k<n;i--,k++){
cout<<endl;
for(j=n-1,l=0;j>=0,l<n;j--,l++)
br[k][l]=arr[i][j];
}
for(i=0;i<n;i++){
for(j=0;j<n;j++)
arr[i][j]=br[i][j];
}
}
int main() {
int i,j,k,l,ar[3][3],br[3][3];
for(i=0;i<3;i++)
for(j=0;j<3;j++)
cin>>ar[i][j];
int n=3;
reve(ar,n);
for(i=0;i<3;i++){
cout<<endl;
for(j=0;j<3;j++)
cout<<ar[i][j];
}
return 0;
}
When you use a 2-d array in a function call, it decays into a pointer type. However, all dimensions but the first one must match exactly.
If the argument type of a function is int (*arg)[2], then, you can't use a variable that is declared as int var[3][3] to call the function. var decays to a pointer whose type is int (*)[3].
It is confusing at first because it seems to work in case of 1-d arrays.
void foo(int arg[10])
{
}
int var[2];
foo(var); // OK
That's because the compiler ignores the size of the first dimension of the array. The above definition of foo is same as:
void foo(int arg[])
{
}
and
void foo(int* arg)
{
}
However, for a multidimensional array, the size of all but the fist dimension must match exactly. Otherwise, they are different types.
The reve() function expects an array of [2][2] but you're passing a [3][3] array.
The ar array in main() is declared as int ar[3][3] while it should have been int ar[rows][cols]
You have reserved 2 blocks in memory. And in your loop, you are taking it from 2 to 0 that makes it 3. Do the following changes.
const int n= 2;
And it should work for your program.
#include <iostream>
using namespace std;
void main()
{
int x[3] = {5,2,4}:
swap(x,1,2);
}
void swap(int[] list, int i, int j)
{
int temp = list[i];
list[i] = list[j];
list[j]= temp;
}
I am trying to figure out what this means, I get the passed by value. However I am not too familiar with pointers and value-results? Will some one explain or point me to an example dealing with C and the methodologies below?
Argument x is passed by value.
Argument x is passed by reference.
Argument x is passed by value-result.
Your confusion is caused by the fact that arrays do not exist in function argument lists.
To elaborate:
void swap(int list[25], int i, int j)
void swap(int list[5], int i, int j)
void swap(int list[], int i, int j)
void swap(int* list, int i, int j)
are actually the same function.
Also:
int arr[30];
int* ptr = arr; // does the same as int* ptr = &arr[0]
These confusing semantics for C-style arrays was the reason why std::array was created.
And to answer your question:
You can't pass C-array by value.
You can pass C-array by reference (void fun(int (&arr)[3]) is a function that takes three-element array by reference)
There is no pass by value-result in C++.
Check this Stack Overflow question for more details about arrays
[You should try this code on your codeblocks. i have explained all arguments in comment line to better understand.][1]
enter code here
https://ideone.com/17oQZV
//function prototype at the top
void fillRandArray(int A[], int number, int maxNum);
//function declaration
void fillRandArray(int* A, int number, int maxNum) {
for(int i = 0; i < number; i++) {
A[i] = rand() % maxNum + 1;
}
}
int A[MAX_STUDENTS];
fillRandArray(A, number, 44);
I dont understand the code, so the prototype set int A[]
then the declaration set int* A
when we pass the argument, shouldn't we pass like this...
fillRandArray(A[MAX_STUDENTS], number, 44); <---- ???
The code below is passing the name of an array, which is an address.
void fillRandArray(int A[], int number, int maxNum);
The code below this is passing just the name of an address, which happens to be A in this case. They are basically doing the same thing.
void fillRandArray(int* A, int number, int maxNum)
You would not pass the argument like the following:
fillRandArray(A[MAX_STUDENTS],..., ...);
because you told the compiler to expect an address, not an element of the array. So you would just pass it A (i.e. the name of array, which is also the starting address). So it would look like this:
fillRandArray(A, number, 44);
Ask more questions, if I didn't explain it well enough.
The problem is that C-style arrays can't be passed as arguments
to a function. When you write int a[] as a parameter in
a function, the compiler translates it to int* a. In
addition, if you provide a dimension (e.g. int a[10]), it is
simply ignored.
Also, an array can convert to a pointer, and will do so in a lot
of contexts. This is what happens in fillRandArray(A, number,
44); the array A is implicitly converting to a pointer.
As for fillRandArray(a[MAX_STUDENTS], number, 44), this
indexes into the array for the first element; with your
declaration, it passes an int (not an array or a pointer),
except that it accesses one beyond the end of the array, so it's
undefined behavior.
In general, you want to avoid this (although with main, you
can't): the function should either take an std::vector<int>&
a, or in a few special cases, an int (&a)[N] (in which case,
the function should be a template, and N be a template
parameter). So you might write:
template <size_t N>
void fillRandArray( int (&a)[N], int maxNumber )
{
for ( int i = 0; i != N; ++ i ) {
a[i] = rand() % maxNum + 1;
}
}
(But for this sort of thing, std::vector is far preferrable.)
Are arrays passed by default by ref or value?
Thanks.
They are passed as pointers. This means that all information about the array size is lost. You would be much better advised to use std::vectors, which can be passed by value or by reference, as you choose, and which therefore retain all their information.
Here's an example of passing an array to a function. Note we have to specify the number of elements specifically, as sizeof(p) would give the size of the pointer.
int add( int * p, int n ) {
int total = 0;
for ( int i = 0; i < n; i++ ) {
total += p[i];
}
return total;
}
int main() {
int a[] = { 1, 7, 42 };
int n = add( a, 3 );
}
First, you cannot pass an array by value in the sense that a copy of the array is made. If you need that functionality, use std::vector or boost::array.
Normally, a pointer to the first element is passed by value. The size of the array is lost in this process and must be passed separately. The following signatures are all equivalent:
void by_pointer(int *p, int size);
void by_pointer(int p[], int size);
void by_pointer(int p[7], int size); // the 7 is ignored in this context!
If you want to pass by reference, the size is part of the type:
void by_reference(int (&a)[7]); // only arrays of size 7 can be passed here!
Often you combine pass by reference with templates, so you can use the function with different statically known sizes:
template<size_t size>
void by_reference(int (&a)[size]);
Hope this helps.
Arrays are special: they are always passed as a pointer to the first element of the array.