在C语言中,用于绝对值函数(接受浮点数)的原型为
float fabsf( float );
为什么这个原型不接受一个常量值,像这样:
float fabsf( float const );
fabsf不会更改输入的值,对吗?
如果我有一个接受输入并调用fabsf的函数,我是否被迫避免将输入指定为const?
在这种情况下处理const正确性的适当方法是什么?
答案 0 :(得分:33)
C使用按值传递。函数参数的值是您提供的参数的副本。
可以同时复制const和非const浮点数,结果是非const浮点数。
这类似于作业:
const float f = 5.5f;
float g = f; // OK
实际上,该语言指定表达式的值永远不能为const
,即,从变量中读取值时,即使该变量为const
也不是该值。 / p>
答案 1 :(得分:14)
修改
正如M.M所评论的那样,对于原型中的参数,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()
将读取给定值,更改其符号,然后返回取反的值。
函数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);
答案 2 :(得分:8)
由于C语言使用按值传递语义,因此您传递给它的 any 参数虽然可以在内部进行修改,但不会直接影响您传递的值。
这意味着从呼叫者的角度来看,float fabsf( float );
和float fabsf( const float );
是相同的。因此,制作参数const
毫无意义。
使用const
有意义的地方是void print_string(char *str)
,如果您传入的参数是指针,例如:
str[0] = 'x'
尽管顾名思义,该函数仍可以取消引用给定指针并修改其指向的内容,即void print_string(const char *str)
,以使调用函数可以看到更改。如果此函数的定义如下:
str
确保调用者无法对{{1}}指向的内容进行任何修改。
答案 3 :(得分:5)
要添加语言律师的观点:
要使两个函数类型兼容,两者都应指定兼容的返回类型。 此外,参数类型列表(如果同时存在)应在 参数和省略号终止符的使用; 相应参数应具有 兼容类型。 [..] 在确定类型 兼容性和复合类型,[..]每个用限定类型声明的参数 被视为具有声明类型的非限定版本。
N1570 6.7.6.3/15
这意味着这两个是兼容的:
void foo(int const);
void foo(int);
因此,您可以编写带有或不带有const
的原型(这意味着没有任何意义;键入/读取的内容更少),并且可以在函数定义中添加const
,以避免不必要的修改。函数主体中的(复制-按值调用!)参数。