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

标签 c constants 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和一个很好的答案here对于 C++

最佳答案

这是函数参数列表规则中的一种特殊情况明确允许的。 N1570 §6.7.6.3p13 1 说:

In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.

但是你也必须明白,像const char *这样的类型的“不合格版本”仍然是const char *,因为类型const char * 派生 const char 类型,并且 §6.2.5p26

A derived type is not qualified by the qualifiers (if any) of the type from which it is derived.

也就是说声明

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 没有原型(prototype),也没有const,所以整个问题都没有实际意义。

关于c - 在 C 中,仅在函数定义中而不是声明中添加 `const` 是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46373266/

相关文章:

rust - Rust 中的不可变变量和 const 变量有什么区别?

c - -Wmissing-field-initializer 使用指定的初始值设定项时

c - 使用 C 在服务器端读取从客户端发送的文本文件

opengl - 为什么程序员在OpenGL中使用常量和静态变量?

c++ - 为什么有时函数会返回一个 const 或 const 引用

c - C中堆栈上的动态数组分配

C 如何避免多次取消引用同一个变量?

c - C 中三角函数的单精度参数约简

c - 当从 MIPS 调用 C 时,我们使用 JR 还是 JALR?

c - Vista 上的性能计数器问题