C++ passing array using reference operator - c++

I have a question about passing array with reference operator. I want to write code that pass array using reference operator. Then I tried
void swap(int &testarray[3]){
// code
}
It gives me error. It says,
/main.cpp:5: error: declaration of 'testarray' as array of references
However when changed my code with
void swap(int (&testarray)[3]){
// code
}
It runs properly. Only difference is having bracket.
Why it needs bracket and what is the difference between int (&testarray)[3] and int &testarray[3]
Thanks for helping.

void foo(int &testarray[3]) is interpreted as void foo((int &)testarray[3]) due to priority. And array of references are illegal.
Whereas void foo(int (&testarray)[3]) is interpreted as you want. (reference of an array of 3 int).
void foo(int testarray[3]) is equivalent to void foo(int testarray[])
which decays to void foo(int *testarray). (int pointer).

In fact this construction
int & testarray[3]
defines an array of references to integral objects. The C++ Standard does not allow to define arrays of references to objects.

Related

How do I pass an array as an reference to a pointer of const char? [duplicate]

How does passing a statically allocated array by reference work?
void foo(int (&myArray)[100])
{
}
int main()
{
int a[100];
foo(a);
}
Does (&myArray)[100] have any meaning or its just a syntax to pass any array by reference?
I don't understand separate parenthesis followed by big brackets here. Thanks.
It's a syntax for array references - you need to use (&array) to clarify to the compiler that you want a reference to an array, rather than the (invalid) array of references int & array[100];.
EDIT: Some clarification.
void foo(int * x);
void foo(int x[100]);
void foo(int x[]);
These three are different ways of declaring the same function. They're all treated as taking an int * parameter, you can pass any size array to them.
void foo(int (&x)[100]);
This only accepts arrays of 100 integers. You can safely use sizeof on x
void foo(int & x[100]); // error
This is parsed as an "array of references" - which isn't legal.
It's just the required syntax:
void Func(int (&myArray)[100])
^ Pass array of 100 int by reference the parameters name is myArray;
void Func(int* myArray)
^ Pass an array. Array decays to a pointer. Thus you lose size information.
void Func(int (*myFunc)(double))
^ Pass a function pointer. The function returns an int and takes a double. The parameter name is myFunc.
It is a syntax. In the function arguments int (&myArray)[100] parenthesis that enclose the &myArray are necessary. if you don't use them, you will be passing an array of references and that is because the subscript operator [] has higher precedence over the & operator.
E.g. int &myArray[100] // array of references
So, by using type construction () you tell the compiler that you want a reference to an array of 100 integers.
E.g int (&myArray)[100] // reference of an array of 100 ints
The following creates a generic function, taking an array of any size and of any type by reference:
template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
// do stuff
}
play with the code.
Arrays are default passed by pointers. You can try modifying an array inside a function call for better understanding.

Template function array loop [duplicate]

How does passing a statically allocated array by reference work?
void foo(int (&myArray)[100])
{
}
int main()
{
int a[100];
foo(a);
}
Does (&myArray)[100] have any meaning or its just a syntax to pass any array by reference?
I don't understand separate parenthesis followed by big brackets here. Thanks.
It's a syntax for array references - you need to use (&array) to clarify to the compiler that you want a reference to an array, rather than the (invalid) array of references int & array[100];.
EDIT: Some clarification.
void foo(int * x);
void foo(int x[100]);
void foo(int x[]);
These three are different ways of declaring the same function. They're all treated as taking an int * parameter, you can pass any size array to them.
void foo(int (&x)[100]);
This only accepts arrays of 100 integers. You can safely use sizeof on x
void foo(int & x[100]); // error
This is parsed as an "array of references" - which isn't legal.
It's just the required syntax:
void Func(int (&myArray)[100])
^ Pass array of 100 int by reference the parameters name is myArray;
void Func(int* myArray)
^ Pass an array. Array decays to a pointer. Thus you lose size information.
void Func(int (*myFunc)(double))
^ Pass a function pointer. The function returns an int and takes a double. The parameter name is myFunc.
It is a syntax. In the function arguments int (&myArray)[100] parenthesis that enclose the &myArray are necessary. if you don't use them, you will be passing an array of references and that is because the subscript operator [] has higher precedence over the & operator.
E.g. int &myArray[100] // array of references
So, by using type construction () you tell the compiler that you want a reference to an array of 100 integers.
E.g int (&myArray)[100] // reference of an array of 100 ints
The following creates a generic function, taking an array of any size and of any type by reference:
template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
// do stuff
}
play with the code.
Arrays are default passed by pointers. You can try modifying an array inside a function call for better understanding.

How to resolve this MISRA c++ compliant warning

int foo(const uint8_t array[]) {
int x;
for(i=0;i<5;i++){
x= array[i];
}
return 0;
}
it gives a warning as below,
"parameter array could be declared const" ==> i already have declared the array const, i am programming in C++.
First thing to note is that int foo(const uint8_t array[]) is equivalent to int foo(const uint8_t* array), i.e. the function takes a pointer to a const uint8_t, not an array. The pointer itself it not const, the pointee is. The signature should be:
int foo(const uint8_t* const array)
For the record, I don't find this warning particularly useful. The parameter is taken by value and the caller couldn't care less what the function does with it. Furthermore, top level const qualifiers on parameters are ignored when comparing function signatures, and this can lead to some confusion.
void foo(int) and void foo(const int), for example, are identical signatures.
EDIT:
So, according to your comment, MISRA doesn't know that you can't pass arrays by value and complains that array indexing works differently than pointer arithmetic. Shudder... The problem is that you can't add top level const using the array syntax, which makes fixes to these two warnings mutualy exclusive.
Try tricking it like this, then:
typedef const uint8_t Array[];
int foo(const Array arr);
Remember that, despite the syntax, the function actually takes a pointer, and is equivalent to
int foo(const uint8_t * array)
So array points to an array of constant bytes; but is not itself constant. The warning is pointing out that, since the function doesn't modify the pointer, it could (and, at least according to this rule, should) be constant:
int foo(const uint8_t * const array)
There is another way and it seems to be under the <iterator>
To move your pointer forward 'safely' you simply use std::advance(array, 1) then to access that value you simply dereference (*array), the location, this seems to get rid of the MISRA warning in question.

Array/pointer/reference confusion [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Confusion over C++ pointer and reference topic
Suppose I am passing
int arr[10];
as a parameter to a function.
Are all of these valid function prototypes? How do they differ in terms of arguments and why?
This is what I know so far (not sure if correct or not)
1. void foo(int &arr); //a reference to an array, which preserve the size attribute?
2. void foo(int &arr[]); //the same (is it)?
3. void foo(int (&arr)[]); //I don't know
4. void foo(int &arr[10]); //is it the same as 2?
5. void foo(int (&arr)[10]);//no idea
6. void foo(int *arr); //a decayed pointer of the array, pointing to the first element of the array, losing the size attribute?
7. void foo(int *arr[]); //the same (is it?)
8. void foo(int (*arr)[]); //a pointer to an array, preserve the size
9. void foo(int *arr[10]); //the same as 7 (is it?)
10. void foo(int (*arr)[10]);//is the same as 8 (is it?)
11. void foo(int arr[]); //is the same as 6 (is it?)
12. void foo(int arr[10]); // is the same as 6 (is it?)
(I know this will need a lengthy explanation, sorry, I'm totally confused...)
The first important piece of information is that parameters whose type is a (bounded or unbounded) array of T are transformed to pointers to T. I.e. both int arr[] and int arr[10] are transformed to int * arr. Note that the transformation is only performed on top-level arrays, i.e. it doesn't occur in int (*arr)[10], which is a pointer to an array of int.
Furthermore, things to the right of the identifier bind more closely than things to the left, i.e. int *arr[10] is an array, whereas int (*arr)[10] is a pointer.
Lastly, arrays of and pointers to references are invalid, as are pointers and references to unbounded arrays.
1. void foo(int &arr); // can't pass, reference to int
2. void foo(int &arr[]); // invalid, pointer to reference to int
3. void foo(int (&arr)[]); // invalid, reference to unbounded array of int
4. void foo(int &arr[10]); // invalid, pointer to reference to int
5. void foo(int (&arr)[10]); // can pass, reference to an array of int
6. void foo(int *arr); // can pass, pointer to int
7. void foo(int *arr[]); // can't pass, pointer to pointer to int
8. void foo(int (*arr)[]); // invalid, pointer to an unbounded array of int.
9. void foo(int *arr[10]); // can't pass, pointer to pointer to int
10. void foo(int (*arr)[10]); // can't pass, pointer to array of int
11. void foo(int arr[]); // can pass, pointer to int
12. void foo(int arr[10]); // can pass, same as above
Using arr as an argument to foo will cause it to decay to a pointer to its first element -- the value passed to foo will be of type int *. Note that you can pass &arr to number 10, in which case a value of type int (*)[10] would be passed and no decay would occur.
The difficult part is to consider that array don't pass by value, but decay into pointers.
Some of your declaration are syntax errors, some other are not (but are also not what you probably think)
In your case, teh only one that make sense are 6, 11 and 12.
2, 3 ,4 and 8 have self explanatory error messages. (if you don't understand them is most likely because you read the declaration with a wrong operator priority)
t1.cpp:2:19: error: declaration of 'arr' as array of references
t1.cpp:3:22: error: parameter 'arr' includes reference to array of unknown bound 'int []'
t1.cpp:4:21: error: declaration of 'arr' as array of references
t1.cpp:8:22: error: parameter 'arr' includes pointer to array of unknown bound 'int []'
The others are somehow redundant (reference-to-array or -pointer-, they will behave the same inside the function) or simply wrong because declaring something different as you intend (like 7,9,10: they represent a "double indirection", while a plain array has a single one, and 1. that doesn't represent any indirection: it just aliases a single int)

Arguments in a function prototype

My question is: when i write a function prototype in C like this:
void foo(int *vector);
It's the same thing to do:
void foo(int vector[MAX_LENGTH]);
To the function, is passed always as a pointer? The code it's the same?
Thanks in advance.
This is subtle. Arrays in C are not pointers, but C does not allow arrays to be passed as function parameters. So when you have void foo(int vector[MAX_LENGTH]);, essentially all you're doing is telling other programmers (and your future self) that this function expects an array of MAX_LENGTH to be passed to it. The compiler won't help you. It will silently cast your array to a pointer.
This explains it pretty well.
Yes an array type is implicitly converted to a pointer type when passed to a function.
So
void foo(int *a) and void foo(int a[]) are identical.
You can easily check that using sizeof() operator inside the function definition
For example
void foo(int a[])
{
std::cout<<sizeof(a); //prints sizeof(int*)
}
int main()
{
int a[]={1,2,3,4};
foo(a);
}
EXTRA (Printing size of an array inside a function)
[C++ Only]
template<typename T,size_t n>
void size_of_array(T (&a)[n]) //Array passed by reference. Template argument deduction
{
std::cout<<sizeof(a); //prints sizeof(n*sizeof(int))
}
int main()
{
int a[]={1,2,3,4,5};
size_of_array(a);
}
This is one of the rough edges of the C language(s). Two declaration that look exactly the same (but for the names), one in the prototype and one as a stack variable, result in the declaration of two different types of variables.
void foo(int A[10]) {
int B[10];
}
Inside the scope of foo, A is pointer to int and B is array of ten elements of type int. As somebody else mentioned, even their sizes computed with sizeof are different.
C++ inherited the rule, so for your example code the prototypes of both functions should be the same.
C99 complicates this matter even further by introducing the new keyword static ;-)
void foo(int A[static 10]) {
int B[10];
}
this doesn't change the rules on how A and B are seen from the inside, but provides an information to the caller side of howmuch array elements are expected. For the moment gcc accepts this new syntax and simply ignores this information.
there's little else it could pass! the [] contraint lets the compiler do more checks though.