Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

arrays in C++: can you explain what this line of code is doing?

Tags:

c++

arrays

I need to modify some C++ code, but since I'm relatively new to the language I'm having trouble understanding some expressions.

I have a function

void func(double m[2][12],double n[2][3])

that is invoked from inside an other function like this

double A[12];
double B[6];
(...)
func( (double (*)[12])A, (double (*)[3])B )

The last line of code is casting a 1D array to a 2D one, but what is happening there exactly? Can I use the same technique to convert a 1D array into a 2D, like this?:

double A[12];
double B[6];
(double (*)[12])A[0][5] = 5;
like image 435
wdg Avatar asked Apr 05 '11 17:04

wdg


2 Answers

What is happening is exactly what you mentioned - the caller is casting the 1 dimensional arrays into in order to pass them to func(), which has two pointer-to-2D-array parameters. Since 2D arrays in C are just 'arrays of arrays' (i.e. there are no pointers involved) this translation is certainly possible. For example, this 1D array:

int oneDimensionalArray[] = { 0, 1, 2, 3 };

and this 2D array:

int twoDimensionalArray[] = { { 0, 1 }, 
                              { 2, 3 } };

Have exactly the same memory layout. You could coerce the types into matching by using crazy-town casting operations like the one in your question.

And as to your second question, yes, you can do that, but you need one more set of parentheses:

((double (*)[12])A)[0][5] = 5;

I don't recommend writing code with this kind of crazy stuff going on, though. Where did the program come from?

like image 121
Carl Norum Avatar answered Oct 14 '22 20:10

Carl Norum


The casting is not from 1D to 2D array but to a pointer to a static 1D array!

double m1[12];

means a variable m1 of type 'static array of 12 doubles'

double m2[2][12];

means a variable m2 of implicitly inferred type 'static array of 2 elements of type "static array of 12 doubles"' When static arrays are used as function arguments they are degenerated to pointers of the type of the array elements. Therefore, for array m1, above we can use any the following functions

f11(double arg[12]) {}  
f12(double * arg) {}

both can be called with any pointer to double or any array of double elements like:

double a=0.0;
double b[10];
f11(&a); f11(b);
f12(&b); f12(b);

Similarly, for array m2 (above), the type of a single element is 'double[12]'. Thus we can use any the following functions:

f21(double arg[2][12]) {}  
f22(double * arg[12]) {}

which can be called with any pointer to 'array of 12 doubles' or any array of elements of type 'array of 12 doubles' like:

double c[12];
double d[6][12];
f21((double (*)[12])c); f21(d);   
f22((double (*)[12])c); f22(d);  

Now for your code, the function void func(double m[2][12],double n[2][3]) actually expects a pointer to 'static array of 12 doubles' and a pointer to 'static array of 3 doubles'. Thus the call that you see

double A[12];
double B[6];
func( (double (*)[12])A, (double (*)[3])B )

actually casts A (which is degenerated to pointer to double) to pointer to 'static array of 12 doubles' and casts B (which is also degenerated to pointer to double) to pointer to 'static array of 3 doubles' Because all of the given arrays work with doubles and static arrays are represented sequentially in memory such casting may not cause logical errors.

like image 34
Assambar Avatar answered Oct 14 '22 19:10

Assambar