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

时间:2017-09-22 21:11:19

标签: c const c99

是否在标准允许的函数参数中添加了额外的const说明符,如下所示?

foo.h

int foo(int x, char * data);

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
}

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

This answer表明C ++标准允许这样做 - C(99)标准是否允许这样做?

还有一个问题here和C ++的好答案here

3 个答案:

答案 0 :(得分:6)

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

  

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

但您还必须了解const char *类型的“不合格版本”仍为const char *,因为类型const char *派生的键入const char§6.2.5p26

  

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

这意味着声明

void foo (const int x);

与定义

兼容
void foo (int x) { ... }

但声明

void bar (const char *x)

与定义

不兼容
void foo (char *x) { ... }

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

1 文件N1570是最接近2011 ISO C标准的,可免费公开发布。

据我所知,这些规则自1989年原始标准以来没有发生重大变化。前C89“K& R”C没有拥有原型,也没有const,所以整个问题都没有实际意义。

答案 1 :(得分:2)

C99 spec,6.7.5.3.15函数声明符,这是合法的:

  

如果一个类型具有参数类型列表而另一个类型由包含(可能为空)标识符列表的函数定义指定,则两者应在参数数量上一致,并且每个原型参数的类型应兼容使用默认参数促销应用到相应标识符类型的类型。 (在确定类型兼容性和复合类型时,使用函数或数组类型声明的每个参数都被视为具有调整类型,并且使用限定类型声明的每个参数被视为具有其声明类型的非限定版本。

答案 2 :(得分:0)

参数上的

cv-qualifiers(而不是参数的 type )不会影响参数的类型,因此不要影响原型。像这样不会影响原型的事情可以在声明和定义之间有所不同,没有任何问题。同样,参数的名称不会影响原型,因此声明和定义之间也可能不同。

现在令人困惑的是,此处出现的const可能在参数上,也可能在参数的类型上,具体取决于它的确切位置。如果它是参数的类型的一部分,则它 影响原型,因此声明和定义之间必须保持一致:

int foo(const int x);   // const on the parameter
int foo(int * const x);  // also const on the parater
int foo(const int *x);  // const in the type, not on the parameter
int foo(int const *x);  // also const in the type