C99 const pass-by-value

时间:2011-01-13 12:43:53

标签: c const c99 pass-by-value

我一直在研究GNU Scientific Library的源代码,并且我一直看到以下类型的声明:

double cblas_ddot (const int N, const double * x, const int incx, const double * y, const int incy)

C99 中,是否有任何(优化)好处来声明通过值传递的参数(例如,上例中的Nincy){{ 1}?无论如何都有一个由他们制作的副本,因为它们是通过价值传递的,不是吗?

THX! 科内尔

3 个答案:

答案 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。

既然你问过,两个版本生成的程序集是相同的。