How do I pass this array to my function?

Hello, I have this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const BYTE original[2][4] = {
	{0x00, 0x00, 0x00, 0x00},
	{0xFF, 0xFF, 0xFF, 0xFF}
};

void function(const BYTE** values)
{
	//some code here
}

int main()
{
	function(original);
	//some code here
}


You might notice that the above code doesn't compile, this is the error:
cannot convert parameter 2 from 'BYTE [2][4]' to 'BYTE *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


Even after some search I couldn't really find an answer to my problem, how do I pass the const BYTE array which I declared above in the function as a parameter (or what structure do I need to set for the function as a parameter)?
Last edited on
In any case your function is declared incorrectly because it is not given numbers of column and rows in the array.

There are three approaches.

Either you can define the function parameter as reference to an array

function( const BYTE ( &values )[2][4] );

and will call it as

function( original );

Or you can define the function parameters as

void function( const BYTE ( *values )[4], size_t nrows );

and will call it as

function( original, 2 );

Or you can define it as

function( const BYTE **values, size_t nrows, size_t ncols );

and will call it as

function( reinterpret_cast<BYTE **>( original ), 2, 4 );

In any case your function is declared incorrectly because it is not given numbers of column and rows in the array.


Nothing is wrong in the declaration of the function if the size of array is not specified. It depends on the user/programmer how he process the array. What I mean to say is, we cannot call this kind of code as incorrect.

function( reinterpret_cast<BYTE **>( original ), 2, 4 );

for 'C' style code, its not necessary to use a C++ cast. A normal C style cast will do the work.
@writetonsharma
Nothing is wrong in the declaration of the function if the size of array is not specified. It depends on the user/programmer how he process the array.


It is obvious that a general case is considered. So this declaration is wrong.

1
2
@writetonsharma
for 'C' style code, its not necessary to use a C++ cast. A normal C style cast will do the work.



This is very strange note because 1) it is not known why did you decide that it is "C style code" 2) in C++ it is better to writte a C++ code.:) 2) reinterpret_cast does the work, does not it?
No one can call it wrong (neither syntactically nor logically unless someone finds a bug in the code) and neither its the only way to tell a function the bounds of an array. You are free to think your way. :-)

Right. So When nothing is specified, its better to keep the code simple and use simple constructs.
@writetonsharma
Right. So When nothing is specified, its better to keep the code simple and use simple constructs


It is not a simple constructrion. It is simply not a good construction that hides the information that the pointer is reinterpreted.
Ok but now I have two problems with that code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const BYTE original[2][4] = {
	{0x00, 0x00, 0x00, 0x00},
	{0xFF, 0xFF, 0xFF, 0xFF}
};

void function(const BYTE **values, size_t nrows, size_t ncols)
{
	//some code here
}

int main()
{
	function(reinterpret_cast<BYTE**>, 2, 4);
	//some code here
}


1) I can't use this code with const, if I do so the compiler says
'reinterpret_cast' : cannot convert from 'const BYTE [2][4]' to 'BYTE **'
1> Conversion loses qualifiers

If I remove the const modifiers however, the code compiles fine

2) If I compile the code as mentioned above, the program crashes when I try to access the array in the function. It does this only when I use the Release build option in VS2010, if I set it to Debug I can access it without trouble.
Last edited on
What does BYTE** have to do with BYTE[2][4]? They are two completely unrelated types. Reinterpreting one as another doesn't change that.

A pointer to a pointer to an element can be used (and is often used in C) when dealing with arrays of pointers to (elements of) arrays, but you aren't dealing with that at all, you're dealing with a 2D array.

To pass
1
2
3
4
const BYTE original[2][4] = {
    {0x00, 0x00, 0x00, 0x00},
    {0xFF, 0xFF, 0xFF, 0xFF}
};

to a function, you can:

1) pass by reference
1
2
3
4
5
6
7
8
9
template<std::size_t nrows, std::size_t ncols>
void function(const BYTE (&values)[nrows][ncols])
{
    // do stuff to values[row][column]
}
int main()
{
    function(original);
}


2) pass a pointer to the first row
1
2
3
4
5
6
7
8
9
template<std::size_t ncols>
void function(const BYTE (*values)[ncols], std::size_t nrows)
{
    // do stuff to values[row][column]
}
int main()
{
    function(original, 2);
}


3) reinterpret your 2D array as a 1D array and pass a pointer to the first element
1
2
3
4
5
6
7
8
void function(const BYTE* values, std::size_t nrows, std::size_t ncols)
{
    // do stuff to values[ncols*row + column]
}
int main()
{
    function(&original[0][0], 2, 4);
}


Or, if you're feeling like wasting some cycles, you can construct an array of pointers to the first elements of the rows of this array, and pass a pointer to the first element of that new array:

1
2
3
4
5
6
7
8
9
void function(const BYTE** values, std::size_t nrows, std::size_t ncols)
{
    // do stuff to values[row][column]
}
int main()
{
    const BYTE* parr[2] = {&original[0][0], &original[1][0]};
    function(parr, 2, 4);
}
I did not take into account that your array is const. Cnahge

reinterpret_cast<BYTE**>,

to

reinterpret_cast<const BYTE**>,

I wonder if that is going to work.


@Zapeth - I would again suggest not going to this extra complexity and use a C cast.

function((const BYTE**)original));

Edit: Surely you don't want to use containers and that's why using double dimension arrays. Why would you want to use C++ cast ?
Last edited on
Thanks Cubbi, I decided to go with solution 1) and it works

Also thanks to all other responses ;)
Last edited on
Topic archived. No new replies allowed.