Search code examples
cc99variable-length-array

Referencing a yet-to-be-mentioned function parameter using the new-style function declarations


Compelled to use the variable length array feature for my auxiliary function that prints square matrices, I defined it as follows:

void print_matrix(M, dim)
     unsigned dim;
     int M[dim][dim];
{
    /* Print the matrix here. */
    ...

The good news is, the code works and has its parameters in the order I'd like them to be.

The bad news is, I had to use the "old-style" function declaration syntax in order to reference the yet-to-be-declared argument dim in the declaration of M, which is apparently considered obsolete and dangerous.

Is there a straightforward way to do the same with the "new-style" function declarations WITHOUT changing the order of the parameters? (And if not, is it considered acceptable use of the old-style syntax in this particular situation?)


Solution

  • In portable (standard) C, you can't do what you show. You have to specify the dimension before the matrix. The original code in the question was:

    void print_matrix(M, dim)
         unsigned dim;
         int (*M)[dim][dim];
    {
    

    and that can't be directly translated — it needs a prototype like this, with the dimension before the matrix:

    void print_matrix(unsigned dim, int (*M)[dim][dim]);
    

    This allows you to call the function with a 3D array. Or, with the revised notation in the question, you can print a 2D array:

    void print_matrix(unsigned dim, int M[dim][dim]);
    

    GCC provides an extension to assist. Quoting the manual:

    If you want to pass the array first and the length afterward, you can use a forward declaration in the parameter list—another GNU extension.

    struct entry
    tester (int len; char data[len][len], int len)
    {
      /* … */
    }
    

    You can write any number of such parameter forward declarations in the parameter list. They can be separated by commas or semicolons, but the last one must end with a semicolon, which is followed by the “real” parameter declarations. Each forward declaration must match a “real” declaration in parameter name and data type. ISO C99 does not support parameter forward declarations.