tyrana4
tyrana4

Reputation: 317

What is the correct way to pass non-const values to functions that take const parameters in C

I have made a function that is supposed to print an array of arrays for testing purposes. Since I don't want to modify anything in the function itself, I thought it would be good to have a const value and const pointer for the function definition.

void test_print(const char*** const array);

/*Some code*/


void test_print(const char*** const command_array){
    int j=0;
    while(command_array[j]!=NULL){
        int k=0;
        while(command_array[j][k]!=NULL){
            printf("%s and %d\n",(command_array[j][k]),j);
            ++k;
        }
        ++j;
    }
}

However if I don't call the function by casting my array like this:

test_print((const char*** const)command_array);

Then I get the error:

invalid conversion from 'char***' to 'const char***'

So my question is: Am I doing the right thing or is there a another way to do this conversion? Is it true to say that this cast will only make the array const inside the function?

Upvotes: 3

Views: 264

Answers (2)

James Anderson
James Anderson

Reputation: 27486

Be careful here. Your compiler may generate subtly different object code for "const" fields.

"const" is also a way of telling the optimizer that the value will never change. Casting to const something that can change may mislead the compiler and produce unxepected results , especially if you are multi-threading environment.

Upvotes: -1

It's not actually safe to cast command_array to const char*** const.

Consider this code:

void test_print(const char*** const command_array)
{
    // command_array is a constant pointer to a non-constant pointer to a non-constant pointer to a constant char

    // we can easily change one of the non-constant levels
    **command_array = "Hello";
}

void fail()
{
    char command[6] = "hello";
    char *level1 = command;
    char **level2 = &level1;
    char ***level3 = &level2;

    ***level3 = 'j'; // valid; now command holds "jello"

    test_print((const char*** const)level3);

    ***level3 = 'z'; // segfault!
}

I believe (meaning I haven't tested this) that const char* const* const* const would be safe, though still not implicitly converted.

The last const is also not necessary - const char* const* const* is the same as const char* const* const* const

Upvotes: 3

Related Questions