what is difference between passing by reference and address in array? - c++

What is the difference between passing by reference and passing by address (using pointer) notation?
Is int arr[] = int* arr ??
I have added three samples of codes, I think the first 2 samples are passing by address and the last one is passing by reference.
void fun(int *arr, unsigned int n)
{
int i;
for (i=0; i<n; i++)
printf("%d ", arr[i]);
}
// Driver program
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
unsigned int n = sizeof(arr)/sizeof(arr[0]);
fun(arr, n);
return 0;
}
#include <stdio.h>
void fun(int arr[], unsigned int n)
{
int i;
for (i=0; i<n; i++)
printf("%d ", arr[i]);
}
// Driver program
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
unsigned int n = sizeof(arr)/sizeof(arr[0]);
fun(arr, n);
return 0;
}
void scale_number(int (&num)[5]);
int main() {
int number[5]={1,2,3,4,5};
scale_number(number);
cout << number << endl;
return 0;
}
void scale_number(int (&num)[5]) {
for(int i=0;i<5;i++)
num[i]=0;
}

is int arr[] = int* arr ??
In short:
In a function parameter declaration: Yes.
Otherwise: No.
Explanation:
int[] is an array of unknown bound of integers.
int* is a pointer to an integer.
A function parameter is never an array. Any function parameter declared to be an array will be adjusted to be a pointer to element of such array. Therefore int[] is adjusted to be int*, but only when it is a function parameter.
i think first 2 samples are passing by address and last one is passing by reference.
Yes. In first two example you pass pointer to an integer, and in the last example you pass a reference to an integer. There is no array in the last example however.
The main differences between pointer and reference are:
Pointers are objects. References are not objects.
Objects have storage (although sometimes it may be optimised away if not observed). It is unspecified whether references have storage - sometimes they do, other times they do not.
There can be pointers-to- and arrays of objects. There cannot be pointers-to- nor arrays of references.
Indirection through pointer is explicit (using one of the indirection operators). Indirection through reference is implicit (operations on a reference are performed on the referred object).
A pointer can be default initialised, and it can point to null. Reference cannot (but reference can become invalid, just like a pointer can).

Related

Cannot convert int(*)[5] to int*

When i tried to access array elements using pointer I got this error i don't understand how can i access with the help of pointer.
Error: cannot convert ‘int (*)[5]’ to ‘int*’ for argument ‘1’ to ‘void addd(int*, int)
Any guidance on the matter would be greatly appreciated!
#include <iostream>
using namespace std;
void addd(int *ptr,int length)
{
cout<<"The values in the array are: ";
for(int i = 0; i < length; i++) {
cout<< *ptr <<" ";
ptr++;
}
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
addd(&arr,5);
//int *ptr = &arr[0];
return 0;
}
Your function receives a pointer to int, so you should just pass the address of the first element.
You can do that:
addd(&arr[0],5);
or simply:
addd(arr,5);
You're doing it wrong. &arr means int (*)[5], but you are using int *ptr. So, you've to use like below:
addd(arr, 5); // this is correct
// addd(&arr, 5) // this is wrong
Here, arr is passed as int *
When you pass an array to a function, for example:
addd(arr,5);
then the array is implicitly converted to a pointer to its first element, an int*. Instead of relying on the implicit conversion, you can make it explicit:
addd( &arr[0],5);
// ^- first element
// ^------ address-of first element
However, arrays are not pointers and taking the address of the array yields a pointer to an array:
using pointer_to_array = int (*)[5];
pointer_to_array p = &arr;
arrays and pointers are pretty much inter-related to each other. An array by default points to the address of the first element, that is the element at index 0. So, working with arrays and pointers are pretty much the same thing( not every time ). So, you do not need to pass on the array as
addd(&arr,5);
you should simply do just
addd(arr,5);
Also , i will say,
The statement
addd(&arr[0],5); does the job, but not a good way to proceed.

Array and pointer

I am wondering how come the # number1 code not working
as I am trying to use increment operator to display the next following element in the array.
But the # number2 code works , and it was the same code but in a function
//# number 1 code
using namespace std;
int main(){
int arrays[5]={2,4,6,8,10};
for(int x=0;x<5;x++){
cout<<*arrays<<endl;
arrays++; //error: lvalue required as increment operand
}
}
//# number 2 code
using namespace std;
void display(int *arr,int size){
for(int x=0; x<5;x++){
cout<<*arr<<endl;
arr++; //This time no error!!!
}
}
int main(){
int arrays[5]={2,4,6,8,10};
display(arrays,5);
return 0;
}
That's because you cannot change the address of an array.
In # number 1 code when you do array++, you are actually trying to operate directly on the variable which is storing the base address of the array.
What you can try instead is something like below:
int *p = array;
p++;
Whereas in the case when you are calling a function passing the array's base address # number 2, you are implicitly doing what has been shown in the above code snippet.
This is a common problem for beginners. Arrays are not pointers!. Arrays are implicitly converted to pointers. That is where the confusion lies. Consider this:
int array[] = {1, 2, 3};
std::cout << *array << '\n';
What do you think is happening when we do *array. Does it really make sense to dereference an array? The array is being implicitly converted to a int * and then dereferenced. What about this:
int array[] = {1, 2, 3};
array++;
std::cout << *array << '\n';
This doesn't compile (as you found out for yourself). In this statement array++, the array is not implicitly converted to a pointer.
Arrays are converted to pointers when you pass them to functions that accept pointers. That makes it possible to do this:
int array[3] = {1, 2, 3};
display(array, 3);
An array is a sequence of objects stored on the stack. You access this sequence of objects as a pointer to the first object. Both arrays and pointers can be subscripted. They share many similarities but are fundamentally different.
To make your first example compile, subscript the array with x:
for (int x = 0; x < 5; x++) {
std::cout << arrays[x] << '\n';
}
Use :
int *arr = arrays;
arr++;
in code #1. It will work. This is because you need first to create a pointer to the base of the array which you can increment as in the second code, you have the pointer in the form of the passed argument to the function.

Why is this sizeof operator giving error?

In this program, the line int len = sizeof(*a)/sizeof(int); gives the error, however if I write this int len = sizeof(**a)/sizeof(int); or this int len = sizeof(a)/sizeof(int);, it works fine. Why is that? Here a holds the address of 1-D array and when I do this, *a, it gives the address of first element of the array and finally **a gives the element itself. So based on this the line int len = sizeof(*a)/sizeof(int); should work fine, isn't it?
#include <stdio.h>
void func(int (*a)[]){
printf("%d %d\n", sizeof(a), sizeof(int));
int len = sizeof(*a)/sizeof(int); // error
for(int i = 0; i < len; ++i){
printf("%d ", (*a)[i]);
}
}
int main(){
int a[][3] = {
{1, 2, 3},
{4, 5, 6}
};
func(a);
return 0;
}
Parameter a is a pointer to an incomplete type. You cannot use sizeof on it since it is a pointer to an array and the size of the array isn't defined.
You can define it:
void func(int (*a)[10]){
In this case sizeof(*a) will equal to sizeof( int )*10 and sizeof(*a)/sizeof(int); will give the element count of a, which is 10 in this case.
Since you are passing a pointer to an array of size 3 you should use 3 not 10.
You can use forward parameters to have a variable sized argument a.
Standard says:
C11: 6.5.3.4
The sizeof operator shall not be applied to an expression that has function type or an incomplete type [..]
An array type of unknown size is an incomplete type (C11: 6.2.5 Types--p22). *a in func is of incomplete type. You need to specify the length of the array a points to before using it as an operand of sizeof.

reference to an array in c++

Question is make an array of 10 integers that's fine
int array[10];
Now question is
how to make a reference to an array which I have declared above ?
I tried this
int &ra = a;
But it's giving me error...
Please provide me details about this error and how to make reference of an array.
int (&ra)[10] = a;
Alternatively, you can use a typedef to separate this into the type for "array of 10 ints" and having a reference there-to, as in:
typedef int int10[10];
int10& my_ref = a;
The problem with your int &ra = a; is that it tells the compiler to create a reference of type int that refers to an array of 10 ints... they're just not the same thing. Consider that sizeof(int) is a tenth of the size of an array of ten ints - they occupy different amounts of memory. What you've asked for with the reference's type could be satisfied by a particular integer, as in int& ra = a[0];.
I appreciate it's a bit confusing that int* p = a; is allowed - for compatibility with the less type-safe C, pointers can be used to access single elements or arrays, despite not preserving any information about the array size. That's one reason to prefer references - they add a little safety and functionality over pointers.
For examples of increased functionality, you can take sizeof my_ref and get the number of bytes in the int array (10 * sizeof(int)), whereas sizeof p would give you the size of the pointer (sizeof(int*)) and sizeof *p == sizeof(int). And you can have code like this that "captures" the array dimension for use within a function:
template <int N>
void f(int (&x)[N])
{
std::cout << "I know this array has " << N << " elements\n";
}
The reference to array will have type int (&a)[10].
int array[10];
int (&a)[10] = array;
Sometimes it might be useful to simplify things a little bit using typedef
typedef int (&ArrayRef)[10];
...
ArrayRef a = array;
This is a reference to an array of of ints of size 10:
int (&ra)[10];
so
int (&ra)[10] = a;
You can typedef the array type (the type should not be incomplete) as follow:
#define LEN 10
typedef int (array)[LEN];
int main(void)
{
array arr = {1, 2, 3, 4, 5}; //define int arr[10] = {1, 2, 3, 4, 5};
array arr2; //declare int arr[10];
array *arrptr = &arr; // pointer to array: int (*arrptr)[10] = &arr;
array &&arrvef; // declare rvalue reference to array of 10 ints
array &ref = arr; // define reference to arr: int (&ref)[10] = arr;
}

How are arrays passed?

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.