在C中,仅在函数定义中添加`const`是合法的,而不是声明吗?

Eri*_*ric 6 c const c99

是否const为标准允许的函数参数添加其他说明符,如下所示?

foo.h:

int foo(int x, char * data);
Run Code Online (Sandbox Code Playgroud)

foo.c:

// does this match the prototype?
int foo(const int x, char * const data) {
    // this implementation promises not to change x or move data inside the function
}
Run Code Online (Sandbox Code Playgroud)

GCC接受它-std=c99 -Wpedantic -Wall -Werror,但不一定与标准兼容.

这个答案表明C++标准允许这样做 - C(99)标准是否允许这样做?


还有另外一个问题,在这里和一个很好的答案在这里为C++

zwo*_*wol 6

功能参数列表的规则中的特殊情况明确允许这一点.N1570§6.7.6.3p13 1说:

在确定类型兼容性和复合类型时,使用函数或数组类型声明的每个参数都被视为具有调整类型,并且使用限定类型声明的每个参数都被视为具有其声明类型的非限定版本.

但你也必须明白,类型的"不合格版本" const char *仍然是const char *,因为类型const char *是从类型派生const char,§6.2.5p26

派生类型不是由派生类型的限定符(如果有)限定的.

这意味着声明

void foo (const int x);
Run Code Online (Sandbox Code Playgroud)

与定义兼容

void foo (int x) { ... }
Run Code Online (Sandbox Code Playgroud)

但声明

void bar (const char *x)
Run Code Online (Sandbox Code Playgroud)

不是与定义兼容

void foo (char *x) { ... }
Run Code Online (Sandbox Code Playgroud)

您可能想知道为什么这些规则就是这样的.简短的版本是,在C,所有参数总是通过复制值(但不是任何指向的数据的价值,如果涉及指针)传递,所以它并不重要的实际参数是否是const T; T无论如何,被叫者都会像普通老人一样接收它.但是,如果将指针复制到常量数据,则复制仍然指向常量数据,因此它确实很重要,应该保留限定符.


1文件N1570是最接近2011 ISO C标准的免费公开版.

据我所知,这些规则自1989年原始标准以来没有发生重大变化.预C89"K&R" C没原型,也未出现const,因此整个问题将变得毫无意义.

  • 如果你认为忽略的cv限定符仅仅影响函数定义中的*局部变量*是`const`还是`volatile`,那么这一切都更有意义.它们与函数的接口无关. (2认同)