1

I have the following c function declaration:

float Sum2d( const unsigned int nRows, const unsigned int mCols, float arr[nRows][mCols] )
{
    float sumAll = 0;

    // I would like to make this change illegal! 
    arr[0][0] = 15;

    for (int i = 0; i < nRows; i++)
        for (int j = 0; j < mCols; j++)
            sumAll += arr[i][j];

    return sumAll;
}

Using the code:

int main()
{
    // define a 2d float array
    float myArr2d[3][2] = {{1,2}, {3,4}, {5,6}};

    // calculate the sum
    float sum = Sum2d(3, 2, myArr2d);

    // print the sum
    printf("%f\n", myOpResult);

    // return 1
    return 1;
}

This function works well, yet there's one problem: the elements of arr can be altered in the Sum2d() function.

How can I change Sum2d()'s prototype to prevent any changes to arr's elements?

11
  • 1
    Declaring the argument const (which does not finitely prevent you from altering it but "makes it harder") float Sum2d( const unsigned int nRows, const unsigned int mCols, const float arr[nRows][mCols] ) Commented Jul 28, 2011 at 19:21
  • Nobody: when I use the prototype you suggested, I get the following error: file.c:71: warning: passing argument 3 of ‘Sum2d’ from incompatible pointer type file.c:38: note: expected ‘const float (*)[(unsigned int)mCols]’ but argument is of type ‘float (*)[2]’ Commented Jul 28, 2011 at 19:44
  • I am using the gnu compiler (Ubuntu Linux) in c99 mode Commented Jul 28, 2011 at 19:44
  • 3
    @Nobody: Sorry, you're wrong. Commented Jul 28, 2011 at 20:20
  • 3
    @hexa: VLA is rather useless as an automatic variable type, but it's extremely useful in the form of pointer-to-VLA types. It allows you to get the compiler to do all the ugly multi-dimensional array indexing arithmetic for you when passing around pointers. And of course if the function can be inlined and the array size is constant, the mults will get optimized out. Commented Jul 28, 2011 at 21:03

3 Answers 3

3

Multidimensional arrays with const qualification are difficult to handle. Basically you have the choice to cast non-const arrays at every call side, to avoid such const arrays as arguments completely, or to deviate by using some sophisticated macros. This is a longer story, you may read it up here.

Sign up to request clarification or add additional context in comments.

Comments

1

I don't know what compiler you're using, but that doesn't compile for me as C or C++.

But regardless, just making arr const should suffice.

Comments

-2

Change the prototype of the function to use const with float

Also you have specified nRows / nCols in array argument, which is not allowed in C. If you don't know the bounds of array, use double pointer.

This approach doesn't prevents typecasting in the function.

#include <stdio.h>

float Sum2d( const unsigned int nRows, const unsigned int mCols, const float arr[][2] )
{
    float sumAll = 0;

    // I would like to make this change illegal! 
    //arr[0][0] = 15;

    for (int i = 0; i < nRows; i++)
        for (int j = 0; j < mCols; j++)
            sumAll += arr[i][j];

    return sumAll;
}

int main()
{
    // define a 2d float array
    float myArr2d[3][2] = {{1,2}, {3,4}, {5,6}};

    // calculate the sum
    float sum = Sum2d(3, 2, (const float (*)[2])myArr2d);

    // print the sum
    printf("%f\n", sum);

    // return 1
    return 1;
}

Since you are using following command line i suppose:

gcc <file.c> -o out -std=c99

Running on Debian Squeeze
$ gcc array.c -o array -std=c99

$ gcc --version       
gcc (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO   
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.             

9 Comments

ASD: thank you. When I use the prototype you suggested, I get the following error: file.c:71: warning: passing argument 3 of ‘Sum2d’ from incompatible pointer type file.c:38: note: expected ‘const float ()[(unsigned int)mCols]’ but argument is of type ‘float ()[2]’
@user3262424 - are you sure? I just tried the code and it behaves as ASD is suggesting.
that's wrong too. "Also you have specified nRows / nCols in array argument, which is not allowed in C." is wrong (it's allowed). Also, const float(*)[2] is not a pointer to a const qualified type. You cannot initialize it by a float(*)[2], because you will try to initialize a X* by a Y*, and X and Y are unrelated in your case (const float[2] vs float[2]). It's not like in C++ where that will work.
I think you need to revise how to pass array as arguments to a function.
"use double pointer" this is one of the urban myth which result in so many complicated and error prone code. C knows very well how to handle multi-dimensional arrays and whenever you may, you should use them.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.