C99 常量值传递

Posted

技术标签:

【中文标题】C99 常量值传递【英文标题】:C99 const pass-by-value 【发布时间】:2011-06-08 11:40:29 【问题描述】:

我一直在研究 GNU 科学库源代码,并且不断看到以下类型的声明:

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

C99 中,声明按值传递的参数(例如,上面示例中的 Nincyconst 是否有任何(优化)好处?反正有一个副本,因为它们是按值传递的,不是吗?

谢谢! 内核

【问题讨论】:

【参考方案1】:

可能对调用者没有好处,但对被调用者而言。声明函数参数 const 与声明其他局部变量 const 具有相同的有益影响,只要您尝试修改它,就会对自己(作为函数的程序员)施加错误。

在不太聪明的实现中,如果函数被内联,这样的声明也可能会对决策产生影响。但我想现在的编译器会直接从函数的定义中推断出什么来做出这样的决定。

这个实现的规范在其接口中表达当然可以看作是对语言的限制。

【讨论】:

【参考方案2】:

是的。选项“const”通常用于声明传递给此函数的任何内容都不会被更改。编译方面,没有区别。还是按值传递的。

【讨论】:

【参考方案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。

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

【讨论】:

在您的示例中,您没有声明参数const,而是声明参数指向的数据。对于指针,OP 要求的内容类似于int*const result。另外,如果我没记错的话,*y++ 首先增加指针然后取消引用它。不会发生任何可能打扰来电者的事情,不是吗? 你是对的,我的错误,应该是(*y)++; 但是,我从来没有说过声明我的参数 const 会影响指针 - 事实上,我的 point例如,它改变了源内存。不过,我已经添加了一个关于标准变量 const 有用性的额外部分。

以上是关于C99 常量值传递的主要内容,如果未能解决你的问题,请参考以下文章

按值、常量值、引用或常量引用传递非 POD 类型

通过值或常量引用传递给函数?

便宜的值传递与常量引用传递

我们如何在 Cassandra“用户定义函数”中传递一个常量值?

java值和地址值传递字符串常量池的理解

传递值为 null 的变量与传递常量 null 时,Sql Server UDF 的行为不同