use*_*205 22 c constants function pass-by-value
在 C 中,绝对值函数(接受浮点数)的原型是
float fabsf( float );
Run Code Online (Sandbox Code Playgroud)
为什么这个原型不接受一个常量值,像这样:
float fabsf( float const );
Run Code Online (Sandbox Code Playgroud)
fabsf 不会改变输入的值,是吗?
如果我有一个接受输入并调用 fabsf 的函数,我是否被迫避免将输入指定为 const?
在这种情况下处理常量正确性的适当方法是什么?
M.M*_*M.M 33
C 使用按值传递。函数参数的值是您提供的参数的副本。
const 和非常量浮点数都可以复制,结果是非常量浮点数。
它类似于赋值:
const float f = 5.5f;
float g = f; // OK
Run Code Online (Sandbox Code Playgroud)
事实上,该语言规定表达式的值永远不能是const,即当从变量中读取值时,const即使变量是,该值也不是。
the*_*bee 15
编辑
正如 MM 所评论的,原型中的参数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;
}
Run Code Online (Sandbox Code Playgroud)
没有错误信息。
无论如何,我会将原件留在原处,希望它可能有所帮助。
原来的
将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;
}
Run Code Online (Sandbox Code Playgroud)
如果没有错误消息,此源将无法编译。
该函数correct()将读取给定值,更改其符号,并返回否定值。
该函数erroneous()似乎有效地执行相同的操作,只是对参数进行了赋值。但由于参数是const不允许的。
接下来,该函数changer()将像之前一样工作,但不会出错。
我们来看一下调用站点:
float f = 3.14159;
float g = correct(f); // or erroneous(f) or changer(f)
Run Code Online (Sandbox Code Playgroud)
变量f作为参数给出将被复制到参数value。即使changer()被调用,它也永远不会改变。
您可能希望将参数视为某种局部变量。实际上,它们在生成的机器代码中大多是这样处理的。
那么,为什么const有时会看到呢?如果将指针定义为参数,您就会看到它。
当您不想更改指向的值时,您需要添加const; 但要在正确的位置上做!
void effective(int const * pointer);
void futile(int * const pointer);
void possible_but_overly_restricted(int const * const pointer);
Run Code Online (Sandbox Code Playgroud)
因为 C 语言使用按值传递语义,您传递给它的任何参数虽然可以在内部修改,但不会直接影响您传入的值。
这意味着从调用者的角度来看,float fabsf( float );和float fabsf( const float );都是一样的。所以制作参数没有意义const。
如果您传入的参数是指针,那么使用确实有意义const,例如:
void print_string(char *str)
Run Code Online (Sandbox Code Playgroud)
这个函数,不管它的名字是什么,都可以取消对给定指针的引用并修改它指向的内容,即str[0] = 'x',导致调用函数可见的更改。如果这个函数是这样定义的:
void print_string(const char *str)
Run Code Online (Sandbox Code Playgroud)
确保调用者无法对str指向的内容执行任何修改。
要添加语言律师的观点:
对于要兼容的两个函数类型,都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面达成一致;相应的参数应具有兼容的类型。[..] 在确定类型兼容性和复合类型时,[..]使用限定类型声明的每个参数都被视为具有其声明类型的非限定版本。
N1570 6.7.6.3/15
这意味着这两个是兼容的:
void foo(int const);
void foo(int);
Run Code Online (Sandbox Code Playgroud)
因此,您可以在有或没有的情况下编写原型const(这意味着没有更有意义;更少键入/读取)并且const如果您想避免意外修改函数内的(复制 - 按值调用!)参数,可以添加函数定义身体。