结构的动态数组和函数调用f(const struct_type * const data [])

时间:2009-05-11 11:54:49

标签: c

以下代码警告不兼容的类型。解决此代码的正确方法是什么?

感谢

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
}

4 个答案:

答案 0 :(得分:4)

编译器抱怨的原因是const声明中的第一个f

尝试使用

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

你不会得到同样的警告。或者,您可以在致电v

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

这有点违反直觉,但在C中,您无法为pointer-to-pointer-to-nonconst传递pointer-to-pointer-to-const。他们提供了一个特殊例外,允许您为pointer-to-nonconst传递pointer-to-const

以下是常见问题解答"Why can't I pass a char ** to a function which expects a const char **?"

  

您可以使用期望pointer-to-T的{​​{1}}(适用于任何类型T)。但是,允许在限定指针类型中轻微不匹配的规则(显式异常)不是递归应用的,而是仅在顶层应用。 (pointer-to-const-Tconst char **,因此例外不适用。)

     

您无法将pointer-to-pointer-to-const-char值分配给char **指针的原因有点模糊。鉴于const char **限定符完全存在,编译器希望帮助您保证不修改const值。这就是为什么你可以将const分配给char *,而不是相反:添加 const char *显然是安全的 - 对于一个简单的指针,但把它拿走会很危险。但是,假设您执行了以下更复杂的分配系列:

const
     

在第3行中,我们将const char c = 'x'; /* 1 */ char *p1; /* 2 */ const char **p2 = &p1; /* 3 */ *p2 = &c; /* 4 */ *p1 = 'X'; /* 5 */ 分配给char **。 (编译器应该抱怨。)在第4行中,我们将const char **分配给const char *;这显然是合法的。在第5行中,我们修改const char *指向的内容 - 这应该是合法的。但是,p1最终指向c,即char *。这是第4行,因为* p2真的是p1。这是在第3行设置的,这是一个不允许的表格的分配,这正是不允许第3行的原因。

     

const分配给char **(如第3行和原始问题中所示)并不会立即造成危险。但它确立了一种情况,即p2的承诺 - 最终指向的价值不会被修改 - 无法保留。

     

(C ++有更复杂的规则来分配const char ** - 合格的指针,它允许你在不引发警告的情况下进行更多种类的赋值,但仍然可以防止无意中尝试修改const值.C ++仍然不会允许将const分配给char **,但这样可以让您将const char **分配给char ** *。)

     

在C中,如果必须分配或传递在第一级间接之外具有限定符不匹配的指针,则必须使用显式强制类型转换(例如,在这种情况下为(const char * const)),尽管如此这种演员阵容的需要可能表明演员没有真正解决的更深层次的问题。

     

参考文献:ISO Sec。 6.1.2.6,Sec。 6.3.16.1,Sec。 6.5.3   H&amp; S Sec。 7.9.1 pp.221-2

答案 1 :(得分:0)

根据Rampion的回答编辑。问题在于f()声明中的double const。

带警告的代码:

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

此编译无需警告:

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

答案 2 :(得分:0)

看看这对你有用:

f(struct_type *data);

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

请告诉我你是怎么过的。

答案 3 :(得分:-1)

f期望获得一个指针数组(const struct_type * [])作为输入。您将指针传递给struct(const struct_type **)的指针。

最好的办法是将IM的签名改为:

void f(const struct_type *const* data);

为什么需要将数组作为参数传递给函数?