现代编译器可以在看到const
. 但是,我从未见过 C 标准库将const
其用于非指针参数。例如memcmp()
就是这样的一个例子。它有 2 个const void *
参数,但它的第三个参数是size_t
.
为什么标准库(和其他库)是这样设计的?为什么我看不到现代代码const size_t
?const int
现代编译器可以在看到const
. 但是,我从未见过 C 标准库将const
其用于非指针参数。例如memcmp()
就是这样的一个例子。它有 2 个const void *
参数,但它的第三个参数是size_t
.
为什么标准库(和其他库)是这样设计的?为什么我看不到现代代码const size_t
?const int
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 *s1
const
那些const
s 意味着不同的东西。在
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);
变量ptr1
、ptr2
和num
被复制到函数中。 memcmp
不承诺不对其进行调整;它只承诺不调整指针指向的内容。实际上,如果证明有效,它可能会增加/减少任何复制的变量,以便逐步遍历数组。如果它想承诺不更改其中任何一个,则声明将是:
int memcmp ( const void *const ptr1, const void *const ptr2, const size_t num );
对于简单的数据类型(如指针和整数),通过这种方式可以获得很少(如果有的话)优化,并且这个函数(和其他)的原始说明符显然没有理由阻止实现在偶然情况下修改变量。
主要原因是库的一致性。size_t
将参数更改为 aconst size_t
将需要确实修改要重写的大小的库。并非库的所有实现都需要使用相同的算法。这是现有库函数没有被适配的主要原因。
新的库函数通常是有目的地使用非const
参数创建的,因此某些机器相关的实现可以使用可修改的参数。
例如,英特尔 C++ 编译器版本实际上在执行期间对参数进行memcmp
倒计时。length
其他一些实现可能不会这样做。