Function nested in array with reference - c++

int main() {
int broccoli,peppers[3]={4,3,2,1} , *zucchini;
zucchini = &peppers[Saute(peppers,1)];
cout<<zucchini<<endl;
}
I know peppers[2] = 2 but just wonder why after Saute function the value of peppers[2] = 3 ? because I think that i only reference the peppers to zucchini and I never declare smtg like this = Saute(&peppers,1)
int Saute(int onions[], int celery) {
celery *= 2;
onions[celery]++;
return celery;
}

In C++, when you pass an array to a function, the array is not copied but passed "as reference" (actually parameter peppers of type int[3] decays to a pointer to the first element of the array, i.e. to an int*, and the type of argument int onions[] is equivalent to int *, too). Hence, when you pass peppers as parameter to function argument onions, and in the function increase a value of the array through onions[celery]++, then you actually increase a value of array pepper.
That's why...
BTW: peppers[3]={4,3,2,1} should be peppers[4]={4,3,2,1}, and you should have got a compiler warning here.

Related

C++: Type of multidimensional array with `variable` size

I can run this
int a = 5;
auto foo = new int [a][4][4];
But when I try this:
int a = 5;
int * foo[4][4];
foo = new int [a][4][4];
I get the error
error: incompatible types in assignment of ‘int (*)[4][4]’ to ‘int* [4][4]’
Question
What type do I have to specify for foo?
Edit:
The goal is to have one single chunk of memory, not an array of pointers.
The error message is a little confusing because it does not state the variable name.
This works:
int a = 5;
int (*foo)[4][4];
foo = new int [a][4][4];
As #john correctly identified:
You're confused between a 2D array of pointers (that's what you wrote) and a pointer to a 2D array (that's what you want).
So what's the difference between pointer to an array and array of pointers. The correct syntax to define a pointer to an array (what you tried to do):
data_type (*var_name)[array_size];
But this defines an array of pointers (what you actually did):
data_type *var_name[array_size];
#OP in your own answer you already found out what the correct type should be – a pointer to an array int (*foo)[4][4], but I thought a little more explanation is also helpful.

size of 2d array passed into a function

Please explain the output of following code.
I was expecting output to be 16 but output is 8.
#include <iostream>
using namespace std;
void xy(int arr[2][2]){
cout << sizeof(arr);
}
int main() {
int arr[2][2] = {{1,2},{3,4}};
xy(arr);
return 0;
}
When you pass an array to a function, it decays to a pointer so you're actually passing int*. sizeof will give the size of the pointer which can vary depending on the system. In this case, it's returning 8 likely because you're on a 64-bit system.
If you want to pass a plain old C-array to a function, you have 2 possibilities.
Pass by reference
Pass by pointer
It seems that you want to pass by reference. But you are using the wrong syntax.
Please see:
void function1(int(&m)[3][4]) // For passing array by reference
{}
void function2(int(*m)[3][4]) // For passing array by pointer
{}
int main()
{
int matrix[3][4]; // Define 2 dimensional array
function1(matrix); // Call by reference
function2(&matrix); // Call via pointer
return 0;
}
What you pass to the function is a decayed pointer to array of int.
Simply correct the syntax and it will work.
Additional hint:
Do not use plain C-style arrays in C++. Never. Please use STL containers.

Why doesn't this pointer get the value at the array index?

#include <iostream>
using namespace std;
int func(int arg0, int *arg1, int *arg2);
int main() {
int *b;
int z;
int a[10];
z = func(*a[0], &a[z], b+a[4]);
}
The following code above gives me an error "invalid type argument of unary '*' (have 'int')". I know that * when used in a declaration creates a pointer and when used with a variable name it gets the value stored at that pointer. In the function func(), it takes 3 parameters, 1 int and 2 int pointers. I think that the first argument passed into the function is giving me an error but I am not understanding why. Shouldn't *a[0] get the value of the first element in the a array which was declared as an int?
No, the * when used on a pointer dereferences the pointer. But a[0] is already equivalent to:
*(a + 0) // And since the offset is 0, this is equivalent to *a.
In other words, dereferencing a pointer to the beginning of the array that has been offset to give you the value of the item at a given 'index'. What YOU wrote is equivalent to:
**(a + 0) // And since the offset is 0, this is equivalent to **a.
Therefore, you are trying to 'dereference' an int, which won't work. Since * is not a valid unary operator for an int, that fails and causes the error you've seen to appear.
*a[0] is the same as **a.
Given the declaration int a[10];, it should be fairly clear that you are not able to dereference a twice.
If you want the first element of the array a, then that is simply a[0].
You could also simplify your example to this, and still get the same error:
int main() {
int a[10];
int b = *a[0];
}

How do you make a function "size-aware" of its parameters?

From here: https://stackoverflow.com/a/3473454/499125
int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
return arr;
}
The definition above can force the compiler to become size-aware of its parameters. This statement seems complex to me. Can someone give an anatomy of this statement or explain how does the statement achieves the size-awareness?
Can this be extended to handle multiple parameters?
It all boils down to being able to read the declaration. A simpler way of writing exactly the same would be:
typedef int int5[5]; // create a typedef
int5& fillarr( int5& ) {
}
As of the exact way of reading the original declaration, just break it into pieces:
int (&fillarr( int (&arr)[5] ))[ 5 ];
^^^^^^^^^^^^^ // A: reference to array of 5 int
^^^^^^ ^^^^^^ // B: reference to array of 5 int
^^^^^^^^ ^ // C: function taking A and returning B
You can split understanding this in two parts, 1) the return value and 2) the parameter type:
int ( &fillarr() )[5] {
static int arr[5];
return arr;
}
We can have a look at the type: int (&fillarr())[5]. To understand this, unfortunately the old C rule: "Declaration is like usage in expressions" doesn't work with references, so let's have a look at a similar declaration instead:
int (*fillarr())[5];
This is a function that returns a pointer instead of a reference to an array of size 5. How do I figure? Well, assume we do have a function f that returns a pointer to an array of ints, how would we access the fifth element? Let's see, we first have to call the function: f(). Then we have to dereference the result *f() and then access the fifth element (which doesn't exist, but ignore that) (*f())[5] which is an int. This is exactly the declaration syntax:
int x;
int (*f())[5];
x = (*f())[5];
// ^^^-------- call f -> yields pointer to array of 5 ints
// ^----------- dereferene the result of f -> yields array of 5 ints
// ^^^---- access the fifth element
Now you only substitute the * for an & because you're returning a reference in your example.
The parameter syntax works analogously.

How do I find the length of "char *" array in C?

I declare the following array:
char* array [2] = { "One", "Two"};
I pass this array to a function. How can I find the length of this array in the function?
You can't find the length of an array after you pass it to a function without extra effort. You'll need to:
Use a container that stores the size, such as vector (recommended).
Pass the size along with it. This will probably require the least modification to your existing code and be the quickest fix.
Use a sentinel value, like C strings do1. This makes finding the length of the array a linear time operation and if you forget the sentinel value your program will likely crash. This is the worst way to do it for most situations.
Use templating to deduct the size of the array as you pass it. You can read about it here: How does this Array Size Template Work?
1 In case you were wondering, most people regret the fact that C strings work this way.
When you pass an array there is NOT an easy way to determine the size within the function.
You can either pass the array size as a parameter
or
use std::vector<std::string>
If you are feeling particularly adventurous you can use some advanced template techniques
In a nutshell it looks something like
template <typename T, size_t N>
void YourFunction( T (&array)[N] )
{
size_t myarraysize = N;
}
C is doing some trickery behind your back.
void foo(int array[]) {
/* ... */
}
void bar(int *array) {
/* ... */
}
Both of these are identical:
6.3.2.1.3: Except when it is the operand of the sizeof operator or the unary & operator,
or is a string literal used to initialize an array, an expression that has type
‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object and is not an lvalue. If
the array object has register storage class, the behavior is undefined.
As a result, you don't know, inside foo() or bar(), if you were
called with an array, a portion of an array, or a pointer to a single
integer:
int a[10];
int b[10];
int c;
foo(a);
foo(&b[1]);
foo(&c);
Some people like to write their functions like: void foo(int *array)
just to remind themselves that they weren't really passed an array,
but rather a pointer to an integer and there may or may not be more
integers elsewhere nearby. Some people like to write their functions
like: void foo(int array[]), to better remind themselves of what the
function expects to be passed to it.
Regardless of which way you like to do it, if you want to know how long
your array is, you've got a few options:
Pass along a length paramenter too. (Think int main(int argc, char
*argv)).
Design your array so every element is non-NULL, except the last
element. (Think char *s="almost a string"; or execve(2).)
Design your function so it takes some other descriptor of the
arguments. (Think printf("%s%i", "hello", 10); -- the string describes
the other arguments. printf(3) uses stdarg(3) argument handling, but
it could just as easily be an array.)
Getting the array-size from the pointer isn't possible. You could just terminate the array with a NULL-pointer. That way your function can search for the NULL-pointer to know the size, or simply just stop processing input once it hits the NULL...
If you mean how long are all the strings added togather.
int n=2;
int size=0;
char* array [n] = { "One", "Two"};
for (int i=0;i<n;++i)
size += strlen(array[i];
Added:
yes thats what im currently doing but i wanted to remove that extra
paramater. oh well –
Probably going to get a bad response for this, but you could always use the first pointer to store the size, as long as you don't deference it or mistake it for actually being a pointer.
char* array [] = { (char*)2,"One", "Two"};
long size=(long)array[0];
for(int i=1; i<= size;++i)
printf("%s",array[i]);
Or you could NULL terminate your array
char* array [] = { "One", "Two", (char*)0 };
for(int i=0;array[i]!=0;++i)
{
printf("%s",array[i]);
}
Use the new C++11 std::array
http://www.cplusplus.com/reference/stl/array/
the standard array has the size method your looking for