Passed by reference and passed by value - c++

#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

Related

Pointer to an Integer Array and Printing Sum

So, I was told to...
"Write a function Adder() that receives a pointer to an integer array as input, and uses this
pointer to return the sum of elements of the array."
And I was pretty successful. My code is
#include <bits/stdc++.h>
using namespace std;
int Adder (int *ptr)
{
int sum=0;
for (int i=0; i<5; i++)
{
sum=*(ptr+i)+sum;
}
return sum;
}
int main(){
int array[5]={1,1,1,1,1};
int sum;
int *ptr=array;
Adder(ptr);
sum=Adder(ptr);
cout<<sum;
}
The thing I can't understand is where I
Adder(ptr)
and then
int Adder (int *ptr)
"ptr" holds the address, right? While, " *ptr " holds the actual value. I can't understand how this worked. Can someone please explain?
The reason why this works is because adding 1 to an int pointer (in your case ptr) will actually add the size of an int (which can vary depending on the machine).
See the answers to this question for a more detailed explanation: Why a pointer + 1 add 4 actually
The line
int Adder (int *ptr)
defines a function that takes a pointer to an int as its argument. In this context, *ptr does not refer to the value ptr is pointing to.
The line
Adder(ptr);
invokes that function, passing the local pointer named ptr.

Unable to generate an error in a case of swap with help of pointers

I was trying to generate an error in swap code in C++. Interestingly, instead of an error, it successfully shows the opposite. My code look like this:
#include<iostream>
using namespace std;
void swap(int *x, int *y)
{
int *tmp = x;
x = y;
y = tmp;
}
int main()
{
int u = 10;
int v = 20;
int * p = &u;
int * q = &v;
swap(*p, *q);
std::cout<<"u :-"<<u<<" v :-"<<v<<endl;
return 0;
}
The value of u and v got swapped. In this, I am passing pointer value instead of reference but the value gets swapped, How?
Exact code can be found at:
https://ideone.com/kMJHL6
swap(*p, *q);
Since the type of *p and *q are not int *, (it's just int) this code doesn't call your swap function. Instead, it calls the function std::swap, which is in standard C++ library, by function overloading resolving.
Your code has using namespace std; - your case is one of examples that show why you shouldn`t use it.
I think that you're calling the swap function of algorithm library, and not your function

What is the difference between A and A[] in function parameter?

//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.)

Passing a 2-D array to a function in c++ via pointer [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I use arrays in C++?
How do I pass 2-D array to function in c++ via pointer.
I get following error when I try the code below.
error: cannot convert 'int (*)[10][10]' to 'int **' for argument '1' to 'void fn(int **)'
void fn(int **a)
{
cout<<a[0][0]<<" "<<a[0][1];
}
int main()
{
int A[10][10];
A[0][0]=1;
A[0][1]=2;
fn(&A); //????
}
A 2d array, created the way you did, is contigous in memory. The compiler needs to know the size of each segment, to be able to move the pointer to the next one in your function. Writing fn(int (*a)[3]) or fn(int a[][3]) is equivalent. But let's take an example
char a[3][3];
a[0][0] = 01;
a[0][1] = 02;
a[0][2] = 03;
a[1][0] = 04;
a[1][1] = 05;
a[1][2] = 06;
a[2][0] = 07;
a[2][1] = 08;
a[2][2] = 09;
will become
|01|02|03|04|05|06|07|08|09|
in memory.
So if you pass a to a function, it needs to know that it has to increase the a ptr by 3 * sizeof(a) to access a[1][0].
In short : the prototype of the function needs to be void fn(int a[][10]) or void fn(int (*a)[10])
According to the link from #R. Martinho Fernandes , the following is valid C++:
int array_of_arrays[6][7];
int (*pointer_to_array)[7] = array_of_arrays;
So the following should also be valid:
void fn (int (*a)[10])
{
cout<<a[0][0]<<" "<<a[0][1];
}
And I believe the following is also valid:
void fn (int a[][10])
{
cout<<a[0][0]<<" "<<a[0][1];
}
You need to declare fn() as
void fn(int (&a)[10][10])
Arrays in C++ can be treated as pointers to the location of the first element of an array. A two dimensional array can be thought of as an array of pointers, and each of the pointers points to another array. While this isn't strictly speaking how arrays are implemented, C supports implicit conversion between arrays and pointers to the first element, and you can think of them as the same. Array[index] is just syntactical sugar for *(Array + index*sizeof(whatever's in the array)). So for your function to work, you can just do:
void fn(int (*a)[10]) {
cout<<a[0][0]<<" "<<a[0][1];
}
int main() {
int A[10][10];
A[0][0]=1;
A[0][1]=2;
fn(A);
}
No need to get the address of the array first, because it's already a pointer. However, because you're using C++, you really should consider using standard containers:
void fn(vector< vector<int> > const&a) {
cout<<a[0][0]<<" "<<a[0][1];
}
int main() {
vector< vector<int> > A( 10, vector<int>(10) );
A[0][0]=1;
A[0][1]=2;
fn(A);
}
C++ needs to know the array size (of one dimension) to perform 2d indexing.
try:
void fn(int a[][10]) {
cout<<a[0][0]<<" "<<a[0][1];
}

swapping 2 items in an array, but not passing it by reference

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.