Passing a 2D Array to function in C++ [duplicate] - c++

This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
How do I use arrays in C++?
(5 answers)
What is array to pointer decay?
(11 answers)
Closed 1 year ago.
I tried passing a 2D array to a function in C++ and I didn`t understand something:
//My array declaration:
int array[5][5]={{....}}; //I declared and filled the array with values
//My different function tries:
void passArr(int **array) //ERROR
void passArr(int *array[5]) //ERROR
void passArr(int *(*array)) //ERROR
void passArr(int (*(*array))) //ERROR
void passArr(int (*array)[5]) //WORKS
All errors were: [Error] cannot convert 'int (*)[5]' to 'int**' for argument '1' to 'void passArr(int**)'
Why do the errors show up and most importantly what is the difference between int *array[5] and int (*array)[5] when passing as an argument?
If int (*array)[5] worked, then why didn´t int *(*array) or int (*(*array))) also work?

In C and C++, a 2D array is an Array-of-Arrays. The first element of a 2D array is the first 1D array it contains. The conversion is specified in C++ Standard - Array-to-pointer Conversion [conv.array]
When you declared a plain-old 2D array as:
int array[5][5]
You have an array of int[5] arrays. As with any array, it is converted to a pointer to its first element on access. The first element being an array of int[5], so the resulting type is:
int (*)[5]
A pointer-to-array-of int[5]. So for your 2D array named array, that is:
int (*array)[5]

They're just different things. Reading from right to left might be helpful.
int array[5][5] -> array of array of int, could decay to pointer to array of int
int (*array)[5] -> pointer to array of int, could be converted from the above
int **array -> pointer to pointer to int
int *(*array) -> same as above
int (*(*array)) -> same as above
int *array[5] -> array of pointer to int

Also, in the "C++" language, it is strongly advisable to use one of the very-many "container classes" for this purpose. Or perhaps a class of your own devising.
"A simple pointer" has no way to convey that it is pointing to "a 2D array," nor what its dimensions are. The extent of its job-description is that it knows how to point to "a bunch of bytes, or nothing."
But if instead you provided your caller with a reference to a class, your caller could now "ask the class" for what it needed, "and the class would magically know." Just hand the class (X,Y) and you either get the right answer or a runtime exception is thrown. Every single time ... and by the way, efficiently.
This is a much more-robust way to write code, and it really is the reason why the C++ language was invented.

Versions 1,3, and 4 are all the same. Version 2 is also the same as 1,3, and 4, because when passing an array to a function the array decays to a pointer.
Version 2 can also be written
void passArr(int* array[5])
Which probably shows the association of the asterisk with the type more clearly: it is an array of five int-pointers. With the array decaying to a pointer, it becomes
void passArr(int** array)
All of them mean that the entry of the array are addresses, pointing to another array:
[ * | * | * | * | * ]
| | | | +-> [,,,,]
| | | +-> [,,,,]
And so on.
What you have is an array when each entry is an array of 5 ints, not a pointer to one (arrays bear a lot of resemblance with pointers, but they aren't pointers!)
Your matrix looks like this:
[ [1,2,3,4,5], [6,,,,], [,,,,], [,,,,], [,,,,] ]
So, array is a pointer to an int[5], not a pointer to pointer to int. And that is what the parentheses do in version 5: int (*array)[5]. This binds the asterisk closer to array.

Related

Pointers and Multi dimensional arrays [duplicate]

In C, I know I can dynamically allocate a two-dimensional array on the heap using the following code:
int** someNumbers = malloc(arrayRows*sizeof(int*));
for (i = 0; i < arrayRows; i++) {
someNumbers[i] = malloc(arrayColumns*sizeof(int));
}
Clearly, this actually creates a one-dimensional array of pointers to a bunch of separate one-dimensional arrays of integers, and "The System" can figure out what I mean when I ask for:
someNumbers[4][2];
But when I statically declare a 2D array, as in the following line...:
int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];
...does a similar structure get created on the stack, or is it of another form completely? (i.e. is it a 1D array of pointers? If not, what is it, and how do references to it get figured out?)
Also, when I said, "The System," what is actually responsible for figuring that out? The kernel? Or does the C compiler sort it out while compiling?
A static two-dimensional array looks like an array of arrays - it's just laid out contiguously in memory. Arrays are not the same thing as pointers, but because you can often use them pretty much interchangeably it can get confusing sometimes. The compiler keeps track properly, though, which makes everything line up nicely. You do have to be careful with static 2D arrays like you mention, since if you try to pass one to a function taking an int ** parameter, bad things are going to happen. Here's a quick example:
int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};
In memory looks like this:
0 1 2 3 4 5
exactly the same as:
int array2[6] = { 0, 1, 2, 3, 4, 5 };
But if you try to pass array1 to this function:
void function1(int **a);
you'll get a warning (and the app will fail to access the array correctly):
warning: passing argument 1 of ‘function1’ from incompatible pointer type
Because a 2D array is not the same as int **. The automatic decaying of an array into a pointer only goes "one level deep" so to speak. You need to declare the function as:
void function2(int a[][2]);
or
void function2(int a[3][2]);
To make everything happy.
This same concept extends to n-dimensional arrays. Taking advantage of this kind of funny business in your application generally only makes it harder to understand, though. So be careful out there.
The answer is based on the idea that C doesn't really have 2D arrays - it has arrays-of-arrays. When you declare this:
int someNumbers[4][2];
You are asking for someNumbers to be an array of 4 elements, where each element of that array is of type int [2] (which is itself an array of 2 ints).
The other part of the puzzle is that arrays are always laid out contiguously in memory. If you ask for:
sometype_t array[4];
then that will always look like this:
| sometype_t | sometype_t | sometype_t | sometype_t |
(4 sometype_t objects laid out next to each other, with no spaces in between). So in your someNumbers array-of-arrays, it'll look like this:
| int [2] | int [2] | int [2] | int [2] |
And each int [2] element is itself an array, that looks like this:
| int | int |
So overall, you get this:
| int | int | int | int | int | int | int | int |
unsigned char MultiArray[5][2]={{0,1},{2,3},{4,5},{6,7},{8,9}};
in memory is equal to:
unsigned char SingleArray[10]={0,1,2,3,4,5,6,7,8,9};
In answer to your also: Both, though the compiler is doing most of the heavy lifting.
In the case of statically allocated arrays, "The System" will be the compiler. It will reserve the memory like it would for any stack variable.
In the case of the malloc'd array, "The System" will be the implementer of malloc (the kernel usually). All the compiler will allocate is the base pointer.
The compiler is always going to handle the type as what they are declared to be except in the example Carl gave where it can figure out interchangeable usage. This is why if you pass in a [][] to a function it must assume that it is a statically allocated flat, where ** is assumed to be pointer to pointer.
Suppose, we have a1 and a2 defined and initialized like below (c99):
int a1[2][2] = {{142,143}, {144,145}};
int **a2 = (int* []){ (int []){242,243}, (int []){244,245} };
a1 is a homogeneous 2D array with plain continuous layout in memory and expression (int*)a1 is evaluated to a pointer to its first element:
a1 --> 142 143 144 145
a2 is initialized from a heterogeneous 2D array and is a pointer to a value of type int*, i.e. dereference expression *a2 evaluates into a value of type int*, memory layout does not have to be continuous:
a2 --> p1 p2
...
p1 --> 242 243
...
p2 --> 244 245
Despite totally different memory layout and access semantics, C-language grammar for array-access expressions looks exactly the same for both homogeneous and heterogeneous 2D array:
expression a1[1][0] will fetch value 144 out of a1 array
expression a2[1][0] will fetch value 244 out of a2 array
Compiler knows that the access-expression for a1 operates on type int[2][2], when the access-expression for a2 operates on type int**. The generated assembly code will follow the homogeneous or heterogeneous access semantics.
The code usually crashes at run-time when array of type int[N][M] is type-casted and then accessed as type int**, for example:
((int**)a1)[1][0] //crash on dereference of a value of type 'int'
To access a particular 2D array consider the memory map for an array declaration as shown in code below:
0 1
a[0]0 1
a[1]2 3
To access each element, its sufficient to just pass which array you are interested in as parameters to the function. Then use offset for column to access each element individually.
int a[2][2] ={{0,1},{2,3}};
void f1(int *ptr);
void f1(int *ptr)
{
int a=0;
int b=0;
a=ptr[0];
b=ptr[1];
printf("%d\n",a);
printf("%d\n",b);
}
int main()
{
f1(a[0]);
f1(a[1]);
return 0;
}

Pointer dimensions when copying an address of multidimensional arra to a pointer

When we have a multidimensional array, and we hope to use a pointer to point to its address. In a book, it says we will do as following.
#include <stdio.h>
int main(){
int a[3][4][5];
int *p[5];
p = a;
return 0;
}
Now, I am quiet confused about the following points:
When I typed the code into CLion, it gives a warning:Incompatible pointer types 'int[5] *' and 'int[3][4][5]', and why is that?
Why does the pointer array *p contains 5 variables instead of 3 variables?
How to use this pointer *p?
Thanks.
1) Because... they are different pointer types! ;) Specifically, a is a three dimensional array of integers, while p is a one dimensional array of pointers to ints. Got that? a contains ints, p contains pointers to ints.
2) Because line int *p[5]; declares it to be 5 long. In C you define how big an array is by the number in the [].
3) Well, if you want p to point to a you would need to make some part of it point to a, as an example p[0] = a;

sizeof() returning different values when called on the same array in the main function and another function [duplicate]

This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 9 years ago.
I need the use the length of a passed array 'X' in a function. The array is created in the main function. I print out the following from the main function:
std::cout << "\n" << sizeof(X);
which yields: 400
The array 'X' is then passed to a function where the length of X is needed. I print out the following from the function:
std::cout << "\n" << sizeof(X);
which yields: 8
I am expecting 400, as my array has 100 float elements. Why does sizeof() not return the same size as when it was called in the main function? (I assure you that there are actually 100 elements in array X because the rest of the program works.)
Thanks for any help!
When you pass a raw array (e.g. declared as int arr[100];) as a parameter to some other function, is it decayed into a pointer (whose size is often 8 on 64 bits processor).
So you declare your array
int arr[100];
then you declare your function
void f(int arr[]);
which is understood as
void (int *arr);
In C++11 you could use std::array so declare
std::array<int,100> arr;
and pass preferably a reference to it:
void f(std::array<int,100> &arr);
(you could pass it by value, but then all the 100 integers would be copied on function invocation).
BTW, consider also std::vector, and take many hours to read a good C++ programming book.
C arrays can be implicitly reduced to pointers and they will be. For sizeof to work correctly you would need to do the following:
template<size_t N>
void func(char (&arr)[N])
{
/* sizeof(arr) == N in this scope */
}
or you could use C++11 std::array.
In main the array size will be 4*100 = 400, but when you pass the address of array to another function it is now a pointer pointing to array, meaning the size of X is now size of pointer in called function.

Complex C declaration

I was just going through some code on the Internet and found this:
float * (*(*foo())[SIZE][SIZE])()
How do I read this declaration? Is there a specific set of rules for reading such complex declarations?
I haven't done this in a while!
Start with foo and go right.
float * (*(*foo())[SIZE][SIZE])()
foo is a function with no arguments...
Can't go right since there's a closing parenthesis. Go left:
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer
Can't go left further, so let's cross the parentheses and go right again
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE ...
Closing parenthesis reached, left again to reach a pointer symbol:
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to ...
Left parenthesis again, so we cross it and go right again:
float *( *(* foo())[SIZE][SIZE])()
float *( *(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments...
And left to the end
float * ( *(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments returning a pointer to float
And whoever wrote that, please teach him to use typedef:
// Function that returns a pointer to float
typedef float* PFloatFunc ();
// Array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();
Standard rule: find the leftmost identifier and work your way out, remembering that [] and () bind before *:
foo -- foo
foo() -- is a function
*foo() -- returning a pointer
(*foo())[SIZE] -- to a SIZE-element array
(*foo())[SIZE][SIZE] -- of SIZE-element arrays
*(*foo())[SIZE][SIZE] -- of pointers
(*(*foo())[SIZE][SIZE])() -- to functions
* (*(*foo())[SIZE][SIZE])() -- returning pointers
float * (*(*foo())[SIZE][SIZE])(); -- to float
So imagine you have a bunch of functions returning pointers to float:
float *quux();
float *bar();
float *bletch();
float *blurga();
Let's say you want to store them in a 2x2 table:
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab is a SIZE x SIZE array of pointers to functions returning pointers to float.
Now let's decide we want a function to return a pointer to that table:
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
Note that you could have several functions that build tables of different functions, or organize the same functions differently:
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
which is the only reason I can think of to do something like this. You shouldn't see types like this in the wild very often (although they do crop up occasionally, and I've been guilty of writing something similarly heinous).
According to cdecl.org
declare foo as function returning pointer to array SIZE of array SIZE
of pointer to function returning pointer to float
Use the spiral rule given by Luchian Grigore if you want to decode it by hand.
The best thing to do here is convert to a series of typedefs.
typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();
Generally, you could try cdecl.org but you'd need to substitute for SIZE
Say you swap SIZE for 12, you'd get:
declare foo as function returning pointer to array 12 of array 12 of
pointer to function returning pointer to float
I'm not sure that really helps you!
Two observations here:
I'm guessing that this code didn't have a comment beside it explaining what the purpose of it was (i.e. not the technical explanation of what it is but what it is achieving from a functional / business perspective) If a programmer needs to use something as complex as this, they should be good enough to explain to future maintainers what purpose it serves.
Certainly in C++ there are more obvious and probably safer ways of achieving the same thing.
This document gaves me the best clue about how to easily ready any C declaration :
http://c-faq.com/decl/spiral.anderson.html
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
[X] or [] => Array X size of ... or Array undefined size of ...
(type1, type2) => function passing type1 and type2 returning ...
* => pointer(s) to ...
Keep doing this in a spiral/clockwise direction until all tokens have been covered.
Always resolve anything in parenthesis first!
Example :
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Question we ask ourselves: What is str?
``str is an...
- We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
``str is an array 10 of...
- Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
``str is an array 10 of pointers to...
- Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
``str is an array 10 of pointers to char''
We have now ``visited'' every token; therefore we are done!
Although most of the answers above are good enough, there is a lack of complete set of rules for decoding complex C declarations. I have provided a complete set below to decode any complex C declaration. This set of rules is actually based on the precedence of operators. Rules such as right hand spiral rules can be thought of as a shortcut for these set of rules.
Before anything else we need to know a few things to decode the declaration.
'Basic Type' of a declaration
A C declaration always has only one basic declaration type. This is at the left most position of a declaration.
For example -
int a - basic type is 'int'
float *p - basic type is 'float'
char (*p)[3] - basic type is 'char'
Precedence and associativity
Next we need to know the precedence order of (), [], and * - dereference operator
(), [] - Associativity is left to right
* - Associativity is right to left
Phrase corresponding to each of the operator above
Next we need to know the decoded phrase corresponding to each operator. Examples ahead will make this point clear.
() - function returning
[SIZE] - array of SIZE
* - pointer to
Now follow the rules below to decode the declaration
Always write the variable name first followed by an 'is'.
For example -
int a - a is ...
float *p - p is ...
char (*p)[3] - p is ...
Always end with basic type
For example -
int a - a is ... int
float *p - p is ... float
char (*p)[3] - p is ... char
Now fill the part in between using the following sub-steps
Starting from the name, follow the operator precedence and associativity to choose next highest priority operator and append the phrase corresponding to it to the middle part of the decoded string.
Repeat the sub step above for the remaining declaration until the decoding process is complete
NOTE 1: For simplicity, I have ignored the arguments of the function however it can be included just after the phrase corresponding to ().
NOTE 2: Parenthesis(()) change the priority order of operators, just like in any arithmetic expression.
NOTE 3: You can use parenthesis in the decoded declaration to increase readability( I have done it in some examples below). Think of each set of () as a single unit.
NOTE 4: A n dimensional array is actually an array of array of ... (n-1 times) array. For ex - int A[2][3] - A is array of 2 (array of 3 int) i.e A is an array of 2 elements in which each element is an array containing 3 integers
Examples
int a - a is int
float *p - p is pointer to float
char (*p)[3] - p is pointer to array of 3 char
Some complex declaration examples
int **p[10] - p is array of 10 pointer to pointer to int
int (*p)[10] - p is pointer to array of 10 int
int *p(char *a) - p is function returning pointer to int
int (*p(char*a))[10] - p is function returning (pointer to (array of 10 int))
int *(*p)() - p is pointer to (function returning (pointer to int))
int (*p()[20])[10] - p is function returning (array of 20 (pointer to (array of 10 int)))
This set of rules can be used with const as well - const qualifier modifies the term to the left of it (if present) otherwise it modifies the term to the right of it.
const int *p[10] - p is array of 10 pointer to int const
int const *p[10] - p is array of 10 pointer to const int (this is same as 7th example)
int *const p[10] - p is array of 10 const pointer to int
Now a really complex example which will not find its use anywhere in practice but nevertheless can be used to demonstrate the decoding process
char *(*(**foo[][8])())[] - foo is array of (array of 8 (pointer to (pointer to (function returning (pointer to (array of (pointer to char)))))))
Now at last decoding for the declaration given in the question
float * (*(*foo())[SIZE][SIZE])() - foo is function returning (pointer to (array of SIZE (array of SIZE (pointer to (function returning pointer to float)))))
The following is the link for the article from which I read this decoding process
Example 10 has been taken from this article
http://www.unixwiz.net/techtips/reading-cdecl.html
from http://cdecl.org/
declare foo as function returning pointer to array SIZE of array SIZE of pointer to function returning pointer to float

What does *array[] mean?

What does this mean? I see it all the time in programs and I don't get it:
int *array[9];
Why is the asterisk there. What is the difference between this declaration and this:
int array[9];
It's an array of pointers to an integer. (array size is 9 elements. Indexes: 0 - 8)
This can also be stated as being an array of integer pointers.
int array[9] , is an array of integers.
an array of 9 pointers to int type
The asterisk means pointer. You can read the Backus-Naur form for C language to see the definitions of types.