4

现代编译器可以在看到const. 但是,我从未见过 C 标准库将const其用于非指针参数。例如memcmp()就是这样的一个例子。它有 2 个const void *参数,但它的第三个参数是size_t.

为什么标准库(和其他库)是这样设计的?为什么我看不到现代代码const size_tconst int

4

3 回答 3

7

C 使用按值调用。将函数参数标记为一点对编译器没有帮助const(请注意,没有任何参数memcmp()is const。指针参数也可以声明const,您可以建议它们应该是:int memcmp(const void * const s1, const void * const s2, size_t const n);。但它们不是)。

它不能帮助编译器标记函数参数的原因const是,从函数的角度来看,函数参数只是一个局部变量。只要函数不获取其地址,编译器就很容易看出该变量从未被修改过。

相反,作为原型 ( ) 一部分的const修饰符是其契约的一部分:它们表示该函数不会修改指向的数据。修饰符永远不会以这种方式用于参数本身,因为调用者不关心函数是否修改其参数:它们只是副本(再次因为 C 使用按值调用)。memcmp()const void *s1const

于 2012-10-06T16:51:09.920 回答
5

那些consts 意味着不同的东西。在

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

const void * ptr1表示memcmp将被ptr1视为指向常量数据并且不会修改它;同样对于const void * ptr2. 因此,调用者知道存储的值不会改变并且可以进行相应的优化。在像这样的函数调用中

int result = memcmp(ptr1, ptr2, num);

变量ptr1ptr2num复制到函数中。 memcmp不承诺不对其进行调整;它只承诺不调整指针指向的内容。实际上,如果证明有效,它可能会增加/减少任何复制的变量,以便逐步遍历数组。如果它想承诺不更改其中任何一个,则声明将是:

int memcmp ( const void *const ptr1, const void *const ptr2, const size_t num );

对于简单的数据类型(如指针和整数),通过这种方式可以获得很少(如果有的话)优化,并且这个函数(和其他)的原始说明符显然没有理由阻止实现在偶然情况下修改变量。

于 2012-10-06T17:00:25.397 回答
0

主要原因是库的一致性。size_t将参数更改为 aconst size_t将需要确实修改要重写的大小的库。并非库的所有实现都需要使用相同的算法。这是现有库函数没有被适配的主要原因。

新的库函数通常是有目的地使用非const参数创建的,因此某些机器相关的实现可以使用可修改的参数。

例如,英特尔 C++ 编译器版本实际上在执行期间对参数进行memcmp倒计时。length其他一些实现可能不会这样做。

于 2012-10-06T16:53:40.797 回答