Dynamic array of structures and function call f (const struct_type * const data [])

The following code warns of an incompatible type. What is the correct way to solve this code?

thanks

typedef struct a_struct struct_type;

void f(const struct_type *const data[], unsigned n);

void test(unsigned n)
{
   struct_type **v;

   assert(n);
   v = malloc(n * sizeof(struct_type *));
   /* fill v with new struct_type (with a malloc per entry) */
   f(v, n); <- WARN on v
}

      

+1


a source to share


4 answers


The reason the compiler is complaining is because of the first declaration const

in the f

.

Try to use

void f(struct_type *const data[], unsigned n);
/*...*/
f( v, n );

      

and you won't get the same warning. Alternatively, you can use v

when you callf



void f(const struct_type *const data[], unsigned n);
/*...*/
f( (const struct_type * const *) v, n );

      

It's a bit intuitive, but in C, you can't pass pointer-to-pointer-to-nonconst

for pointer-to-pointer-to-const

. They made a special exception so you can pass pointer-to-nonconst

for pointer-to-const

.

Here the question FAQ FAQ "Why can not I pass char **

a function expecting const char **

?
:

You can use pointer-to-T

(for any type T

) where expected pointer-to-const-T

. However, the rule (explicit exception) that allows small inconsistencies in qualified pointer types is not applied recursively, but only at the top level. ( const char **

is pointer-to-pointer-to-const-char

, and the exception therefore does not apply.)

The reason why you cannot assign a value to a char **

pointer const char **

is somewhat unclear. Given that the qualifier const

exists at all, the compiler would like to help you keep promises from changing values const

. This is why you can assign char *

to const char *

, but not the other way around: it is clearly safe to add const

-ness to a simple pointer, but it would be dangerous to take it away. However, suppose you have completed the following more complex series of tasks:

const char c = 'x';     /* 1 */
char *p1;           /* 2 */
const char **p2 = &p1;      /* 3 */
*p2 = &c;           /* 4 */
*p1 = 'X';          /* 5 */

      

On line 3, we assign a to char **

a const char **

. (The compiler should be complaining.) On line 4, we assign const char *

a const char *

; this is clearly legal. On line 5, we modify what a indicates char *

- it should be legal. However, p1 ends up pointing to c, which is const

. This happened on line 4 because * p2 was indeed p1. This was set up on line 3, which is the destination of the form, which is prohibited, which is why line 3 is prohibited.

The assignment to char **

a const char **

(in both line 3 and the original question) is not an immediate danger. But it sets up a situation in which p2 promises - that the value will ultimately not be changed - cannot be saved.

(C ++ has more sophisticated rules for assigning const

-qualified pointers that allow you to do more kinds of assignments without generating warnings, but still guard against inadvertent attempts to change values const

. C ++ still won't allow assigning char **

to const char **

, but that will get you away with assignment char **

to const char * const

*.)

In C, if you must assign or pass pointers that have a qualifier mismatch other than the first level of indirection, then you must use explicit casts (e.g. ( const char **

)), although, as always, the need for such a cast may indicate more a deep problem that casting doesn't really fix.

References: ISO Sec. 6.1.2.6 Clause 6.3.16.1 Clause 6.5.3 H & S Sec. 7.9.1 p. 221-2

+4


a source


Edited based on Rampion's answer. The problem is the double const declaration in the f () declaration.

Warning code:

struct_type ** v;
v = (struct_type **)malloc(10 * sizeof(struct_type *));      
f(v);

      



This compiles without warning:

const struct_type *const* v;
v = (const struct_type **)malloc(10 * sizeof(struct_type *));
f(v);

      

0


a source


See if this works for you:

f(struct_type *data);

void test(unsigned n)
{
    struct_type *v = malloc(n * sizeof(struct_type *));
    f(v);
}

      

Please let me know how you are doing.

0


a source


f expects an array of pointers (const struct_type * []) ​​to be entered as input. You are passing a pointer to a struct pointer (const struct_type **).

The best thing to do, IMO, is change the f signature to:

void f(const struct_type *const* data);

      

Why do you need to pass arrays as arguments to functions?

-1


a source







All Articles