本文介绍了C函数中的奇怪警告const多维数组参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  typedef double mat4 [4] [4]; 

void mprod4(mat4 r,const mat4 a,const mat4 b)
{
/ * yes,函数为空* /
}

int main()
{
mat4 mr,ma,mb;
mprod4(mr,ma,mb);
}

gcc 输出为如下所示:

$ $ $ $ gcc -o test test.c
test.c:在函数'main'中:
test.c:13:warning:从不兼容指针传递'mprod4'的参数2
类型
test.c:4:注意:期望'const double(*)[4]'但参数是'double
(*)[4]'
test.c:13:warning:从不兼容的指针传递'mprod4'的参数3
类型
test.c :4:
note:expected'const double(*)[4]'but argument is of type'double
(*)[4]'

如果我将函数定义为:

  void mprod4 (mat4 r,mat4 a,mat4 b)
{
}

或者在主体中定义矩阵为:

  mat4 mr; 
const mat4 ma;
const mat4 mb;

或者在main中调用该函数:

  mprod4(mr,(const double(*)[4])ma,(const double(*)[4])mb); 

甚至可以将 mat4 定义为:

  typedef double mat4 [16]; 

使警告消失。这里发生了什么?我做的东西无效?



gcc版本是4.4.3,如果相关的话。



我也发布了在gcc bugzilla上:



我当前的解决方法是制作丑陋的宏来为我投射东西:

  #ifndef _NO_UGLY_MATRIX_MACROS 

#define mprod4(r,a,b)mprod4(r,(const double(*)[4])a,(const double(*)[4])b)

#endif






Joseph S. Myers在gcc bugzilla上的答案:

听起来很让人困惑,就像函数期望的那样: p>

 指向数组[4]的const double的

并且我们正在传递

 指向double数组$ [





或者它会是逆?警告提示该函数需要一个:

pre $ const double(*)[4]

这在我看来更像是一个

 指向常量数组[4]的双打

我对这个答案感到困惑。是否有人理解他所说的澄清和举例?

解决方案

我相信问题是在 C99 6.5.16.1(1),它似乎禁止赋值中的混合限定,除了定义了包含限定符异常的指针外。问题在于,对于间接指针,您最终会将指向某个指针的指针传递给另一个指针。这个赋值是无效的,因为如果是这样的话,你可以用它来修改一个const限定的对象:

  const char ** cpp; 
char * p;
const char c ='A';
cpp =& p; //违反约束条件
* cpp =& c; //有效
* p = 0; //本身有效,但会破坏c

看起来合理的是 cpp ,它承诺不会修改任何 char s,可能会分配一个指向指向非限定秒。毕竟,这允许使用单一间接指针,这就是为什么,例如,您可以将可变对象传递给第二个参数 strcpy(3),这是第一个参数 strchr(3),以及许多用 const 声明的参数。



但是对于间接指针,在下一级,允许从限定指针进行赋值,现在完全不合格的指针赋值将会打断合格对象。

我不会立即看到二维数组如何导致这种情况,但无论如何它在标准中遇到相同的约束。

因为在你的情况下,你实际上并没有把它变成clobbering一个const,你的代码的正确的东西似乎是插入




更新:好吧,碰巧这个问题是 ,而且整个讨论也发生过几次 和关于gcc邮件列表。




  • 海湾合作委员会错误清单:
  • C FAQ:问题11.10:



课程:您可以传递 T * x >当通过显式异常,但是 T * x 和<$时,期望 const T * x c $ c> const T * x 仍然是不同的类型,所以你不能将一个指针传递给另一个指向另一个指针。


I'm getting some strange warnings about this code:

typedef double mat4[4][4];

void mprod4(mat4 r, const mat4 a, const mat4 b)
{
/* yes, function is empty */
}

int main()
{
    mat4 mr, ma, mb;
    mprod4(mr, ma, mb);
}

gcc output as follows:

$ gcc -o test test.c
test.c: In function 'main':
test.c:13: warning: passing argument 2 of 'mprod4' from incompatible pointer
type
test.c:4: note: expected 'const double (*)[4]' but argument is of type 'double
(*)[4]'
test.c:13: warning: passing argument 3 of 'mprod4' from incompatible pointer
type
test.c:4:
note: expected 'const double (*)[4]' but argument is of type 'double
(*)[4]'

If I define the function as:

void mprod4(mat4 r, mat4 a, mat4 b)
{
}

Or defining matrices in main as:

mat4 mr;
const mat4 ma;
const mat4 mb;

Or call the function in main as:

mprod4(mr, (const double(*)[4])ma, (const double(*)[4])mb);

Or even defining mat4 as:

typedef double mat4[16];

Makes the warning go away. What is happening here? Am I doing something invalid?

The gcc version is 4.4.3, if relevant.

I also posted on gcc bugzilla: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47143

My current workaround is making ugly macros that cast stuff for me:

#ifndef _NO_UGLY_MATRIX_MACROS

#define mprod4(r, a, b) mprod4(r, (const double(*)[4])a, (const double(*)[4])b)

#endif


Answer from Joseph S. Myers on gcc bugzilla:

Sounds pretty confusing to me, like the function expects:

pointer to array[4] of const doubles

and we are passing

pointer to const array[4] of doubles

intead.

Or would it be the inverse? The warnings suggest that the function expects a:

const double (*)[4]

which seems to me more like a

pointer to const array[4] of doubles

I'm really confused with this answer. Could somebody who understands what he said clarify and exemplify?

解决方案

I believe the problem is the constraints specified in C99 6.5.16.1(1), which seem to prohibit mixing qualifications in assignments, except for pointers for which an inclusive-qualifier exception is defined. The problem is that with indirect pointers, you end up passing a pointer to one thing to a pointer to another. The assignment isn't valid because, if it was, you could fool it into modifying a const-qualified object with the following code:

const char **cpp;
char *p;
const char c = 'A';
cpp = &p;  // constraint violation
*cpp = &c; // valid
*p = 0;    // valid by itself, but would clobber c

It might seem reasonable that cpp, which promises not to modify any chars, might be assigned a pointer to an object pointing at non-qualified chars. After all, that's allowed for single-indirect pointers, which is why, e.g., you can pass a mutable object to the second parameter of strcpy(3), the first parameter to strchr(3), and many other parameters that are declared with const.

But with the indirect pointer, at the next level, assignment from a qualified pointer is allowed, and now a perfectly unqualified pointer assignment will clobber a qualified object.

I don't immediately see how a 2-D array could lead to this situation, but in any case it hits the same constraint in the standard.

Since in your case, you aren't actually tricking it into clobbering a const, the right thing for your code would seem to be inserting the cast.


Update: OK guys, as it happens this issue is in the C faq, and this entire discussion has also taken place several times on the gcc bug list and on the gcc mailing list.

The lesson: you can pass a T *x when const T *x is expected, by explicit exception, but T *x and const T *x are still distinct types, so you can't pass a pointer to either one to a pointer to the other.

这篇关于C函数中的奇怪警告const多维数组参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 07:35
查看更多