为什么 C 中的绝对值函数不接受 const 输入?

Why don't the absolute value functions in C accept const inputs?

在 C 中,绝对值函数(接受浮点数)的原型是

 float fabsf( float );

为什么这个原型不接受一个常量值,像这样:

 float fabsf( float const );

fabsf 不会改变输入的值吧?

如果我有一个接受输入并调用 fabsf 的函数,我是否被迫避免将输入指定为 const?

在这种情况下处理 const 正确性的适当方法是什么?

C 使用按值传递。函数参数的值是您提供的参数的副本。

常量和非常量浮点数都可以复制,结果是非常量浮点数。

类似于赋值:

const float f = 5.5f;
float g = f;   // OK

事实上,该语言指定表达式的值永远不能是 const,即当从变量中读取值时,即使变量是.

编辑

正如 M.M 评论的那样,prototypes 中的参数 const 被忽略。原始答案的编辑来源(见下文)显示:

float correct(float const value);

float erroneous(float const value);

float changer(float value);

float correct(float value) {
  return -value;
}

float erroneous(float value) {
  value = -value;
  return value;
}

float changer(float value) {
    value = -value;
    return value;
}

没有错误信息。

无论如何,我会保留原件,希望它能有所帮助。


原创

参数处的 const 使此 参数 在函数内为只读。

例如:

float correct(float const value) {
  return -value;
}

float erroneous(float const value) {
  value = -value;
  return value;
}

float changer(float value) {
  value = -value;
  return value;
}

如果没有错误消息,此源将无法编译。

函数 correct() 将读取给定值,更改其符号,并 return 取反值。

函数 erroneous() 似乎有效地执行相同的操作,只是对参数进行了赋值。但是因为参数是 const 这是不允许的。

接下来,函数 changer() 将像之前的两者一样工作,但不会出错。

我们来看调用站点:

float f = 3.14159;
float g = correct(f); // or erroneous(f) or changer(f)

作为参数给出的变量 f 将被 复制 到参数 value 中。即使调用changer()也不会改变。

您可能希望将参数视为某种局部变量。其实在生成的机器码中大多是这样处理的


那么,为什么有时会看到 const?如果将 指针 定义为参数,您会看到它。

当不想让指向的值改变时,需要加上const;但要在正确的位置进行!

void effective(int const * pointer);

void futile(int * const pointer);

void possible_but_overly_restricted(int const * const pointer);

因为 C 语言使用按值传递语义,您传递给它的任何参数虽然可以在内部修改,但不会直接影响您传递的值.

这意味着从调用者的角度来看,float fabsf( float );float fabsf( const float );是一样的。所以参数 const.

没有意义

如果您传入的参数是指针, 使用 const 有意义,例如:

void print_string(char *str)

尽管顾名思义,此函数可以解除对给定指针的引用并修改它指向的内容,即 str[0] = 'x',从而导致调用函数可见的更改。如果这个函数是这样定义的:

void print_string(const char *str)

确保调用者函数不能对 str 指向的内容执行任何修改。

添加语言律师视角:

For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. [..] In the determination of type compatibility and of a composite type, [..] each parameter declared with qualified type is taken as having the unqualified version of its declared type.

N1570 6.7.6.3/15

这意味着这两个是兼容的:

void foo(int const);
void foo(int);

因此,您可以编写带或不带 const 的原型(这意味着不带更有意义;输入/读取更少),如果您想避免,可以在函数定义中添加 const不小心修改了函数体内的(复制 - 按值调用!)参数。