Passing array to a function (and why it does not work in C++)
In C, it is possible to use function parameters to define the size of a variable length array parameter as long as the size comes before the array in the parameter list. This is not supported in C++.
The reason it works in C, but not in C++ is simply because it's C code and not C++. The two languages share a history, not a grammar.
The C++ method to pass variable-sized arrays is std::vector
, probably by reference if you intend to modify the vector in the function, or by const
reference if you don't.
What I don't understand is why the compiler allows for sizing in the arrays. To the best of my understanding, either the sizes must be fixed (e.g. xu_col[9][7]) or undefined (e.g. xu_col[][]). In the above code, it appears that the sizes are not compile-time constants.
You are right, the sizes are not compile-time constants. If you have a two-dimensional array, x[line][col] the compiler needs the number of elements in a line to calculate the address of an element. Look at get_char_2() and get_char_3() example code.
If you use variable length arrays (VLAs) as function parameters you have to supply these number (see get_char_1 example). you can write:
my_func( x[][width] )
or you can write
my_func( x[999][width] )
Is the compiler just ignoring the arguments here? or is it really doing a >compile-time check on the dimensions?
The first number (999) will be ignored by the compiler. The second is needed. Without the line size, the compiler can not calculate addresses inside these 2D-array. The compiler does not do run-time or compile-time checks for VLAs in C.
/* file: vla.c
*
* variable length array example
*
* compile with:
*
* gcc -g -Wall -o vla vla.c
*
*/
#include <stdio.h>
#include <wchar.h>
/* 4 Lines - each line has 8 wide-characters */
wchar_t tab[][8] = {
{ L"12345678" },
{ L"abcdefgh" },
{ L"ijklmnop" },
{ L"qrstuvwx" }
};
/* memory layout:
0x00: 0x0031 0x0032 0x0033 0x0034 0x0035 0x0036 0x0037 0x0038
0x20: 0x0061 0x0062 0x0063 0x0064 0x0065 0x0066 0x0067 0x0068
...
*/
/* get character from table w/o variable length array and w/o type */
char get_char_3(int line, int col, int width, int typesize, void *ptr )
{
char ch = * (char *) (ptr + width * typesize * line + col * typesize );
printf("line:%d col:%d char:%c\n", line, col, ch );
return ch;
}
/* get character from table w/o variable length array */
char get_char_2(int line, int col, int width, wchar_t *ptr)
{
char ch = (char) (ptr + width * line)[col];
printf("line:%d col:%d char:%c\n", line, col, ch );
return ch;
}
/* get character from table : compiler does not know line length for
address calculation until you supply it (width).
*/
char get_char_1(int line, int col, int width, wchar_t aptr[][width] )
{
/* run-time calculation:
(width * sizeof(char) * line) + col
??? KNOWN KOWN KNOWN
*/
char ch = (char) aptr[line][col];
printf("line:%d col:%d char:%c\n", line, col, ch );
return ch;
}
int main(void)
{
char ch;
ch = tab[1][7]; /* compiler knows line length */
printf("at 1,7 we have: %c\n", ch );
/* sizeof tab[0][0] == sizeof(wchar_t) */
ch = get_char_1(1,7, sizeof(tab[0])/sizeof(tab[0][0]), tab);
printf("1 returned char: %c\n", ch );
ch = get_char_2(1,7, sizeof(tab[0])/sizeof(tab[0][0]), (wchar_t*)tab);
printf("2 returned char: %c\n", ch );
ch = get_char_3(1,7, sizeof(tab[0])/sizeof(tab[0][0]),
sizeof( wchar_t), tab);
printf("3 returned char: %c\n", ch );
printf("table size: %lu, line size: %lu, element size: %lu\n",
sizeof(tab),
sizeof(tab[0]),
sizeof(tab[0][0])
);
printf("number of elements per lines: %lu\n",
sizeof(tab[0])/sizeof(tab[0][0]));
printf("number of lines: %lu\n",
sizeof(tab)/sizeof(tab[0]));
return 0;
}
All that it does (in C) is allow you to write indexing code in the called funcion without having to do the address calculation yourself, for example:
double d= xu_col[i*row_size + j]; //get element [i,j]
versus
double d= xu_col[i][j];