我一直在研究 GNU Scientific Library 源代码,并且不断看到以下类型的声明:
double cblas_ddot (const int N, const double * x, const int incx, const double * y, const int incy)
在C99中,声明一个按值传递的参数(例如N
或incy
在上面的示例中)是否有任何(优化)好处const
?无论如何,它们都有一个副本,因为它们是按值传递的,不是吗?
谢谢!内核
我一直在研究 GNU Scientific Library 源代码,并且不断看到以下类型的声明:
double cblas_ddot (const int N, const double * x, const int incx, const double * y, const int incy)
在C99中,声明一个按值传递的参数(例如N
或incy
在上面的示例中)是否有任何(优化)好处const
?无论如何,它们都有一个副本,因为它们是按值传递的,不是吗?
谢谢!内核
调用者可能没有任何好处,但被调用者。声明函数参数const
与声明其他局部变量具有相同的有益影响,const
只要您尝试修改它,就会对自己(作为函数的程序员)施加错误。
在不太聪明的实现中,如果函数被内联,这样的声明也可能会对决策产生影响。但我想现在的编译器会对他们直接从函数的定义中推断出的内容做出这样的决定。
当然,可以将这种实现规范在其接口中表示为对语言的限制。
是的。选项“const”通常用于声明传递给此函数的任何内容都不会被更改。编译方面,没有区别。它仍然是按值传递的。
正如其他人所说,以这种方式声明函数,以便在函数的范围内,该变量将不可更改,并且在这样做时,您的编译器应该警告您。
至于您为什么要这样做,请考虑传递指针允许您执行的操作 - 即,您可以取消引用已传递的指针并编辑它指向的数据的值。使用 const 是防止自己意外编辑调用者认为未更改的值的好方法。
例如,考虑这个:
#include <stdio.h>
void add(int* result, const int* x, int* y)
{
*result = *x + *y;
(*y)++; /* <-- the caller won't expect this! */
}
int main(int argc, char** argv)
{
int a = 7;
int b = 10;
int c = 0;
add(&c, &a, &b);
printf("%d + %d = %d\n", a, b, c);
return 0;
}
这吐出来了7+11=17
。现在这是一个微不足道的、不严重的案例,但如果我们依赖任何重要的事情,各种各样的事情都可能发生……
如果你坚持 const 反对 y 变量,你应该得到:
constexample.c:在函数'add'中:constexample.c:7:5:错误:只读位置'*y'的增量</p>
编辑,以进一步澄清:
为非指针变量声明const
类型的一个很好的理由是用于表示某物大小的变量,或任何保存数组最大值的变量。考虑:
int editstring(char* result, ..., const char* source, const size_t source_len);
现在,你对自己说,但我永远不会编辑source_len
. 好吧,让我们在你的算法中说你出于任何原因这样做。如果您的更改增加了 source_len 的值,那么您将面临访问超出您分配的内存的风险。const
如果您尝试修改该值,设置那里将产生编译器错误。
我应该用双下划线指出, const 只是对编译器说“我保证不会编辑它”的一种方式。它不保证内存是只读的,但它是一种标记您的意图的方式,以便您捕获错误。如果您不需要修改它,请将其声明为 const。
既然你问了,两个版本生成的程序集是相同的。