我一直在研究GNU Scientific Library的源代码,并且我一直看到以下类型的声明:
double cblas_ddot (const int N, const double * x, const int incx, const double * y, const int incy)
在 C99 中,是否有任何(优化)好处来声明通过值传递的参数(例如,上例中的N
或incy
){{ 1}?无论如何都有一个由他们制作的副本,因为它们是通过价值传递的,不是吗?
THX! 科内尔
答案 0 :(得分:11)
调用者可能没有任何好处,但对于被调用者而言。声明函数参数const
与通过在尝试修改此函数时对自己(作为函数的程序员)强加错误来声明其他局部变量const
具有相同的有益影响。
在不太智能的实现中,如果函数内联,这样的声明可能也会对决策产生影响。但我想现在编译器会根据函数的定义直接推断出它的决定。
它当然可以被视为对语言的限制,即在其界面中表达了该实现的规范。
答案 1 :(得分:3)
是。选项“const”通常用于表示传递给此函数的任何内容都不会被更改。编译方面,没有区别。它仍然按价值传递。
答案 2 :(得分:3)
正如其他人所说,函数是以这种方式声明的,因此,在函数范围内,该变量将不可更改,并且在这样做时,编译器应警告您。
至于为什么你可能想要这样做,考虑一下指针允许你做什么 - 也就是说,你可以取消引用你传递的指针并编辑它指向的数据的值。使用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'
编辑,以进一步澄清:
为非指针变量声明const
类型的一个很好的理由是表示某事物大小的变量,或者保存数组最大值的任何变量。考虑:
int editstring(char* result, ..., const char* source, const size_t source_len);
现在,你对自己说,但我永远不会编辑source_len
。好吧,让我们说你的算法无论出于何种原因。如果您的更改增加了source_len的值,则存在超出已分配内存的访问内存的风险。如果您尝试修改该值,则设置const
将生成编译器错误。
我应该指出,在双下划线中,const只是对编译器说“我保证不编辑它”的一种方式。它不保证内存是只读,但它是一种标记您的意图以便捕获错误的方法。如果您不需要修改它,请将其声明为const。
既然你问过,两个版本生成的程序集是相同的。