编译器优化:C中非指针函数参数的const

时间:2012-10-06 16:39:03

标签: c compiler-construction const compiler-optimization

现代编译器可以在看到const时优化代码。 但是,我从未见过C标准库使用const作为非指针参数。例如memcmp()就是一个例子。它有2个const void *个参数,但它的第三个参数是size_t

为什么标准库(和其他库)以这种方式设计?为什么我在现代代码中看不到const size_tconst int

3 个答案:

答案 0 :(得分:6)

C使用call-by-value。它没有帮助编译器将函数参数标记为const(注意memcmp()的任何参数都不是const。指针参数也可以声明为{{1}你可以建议它们应该是:const。但它们不是。)

它无法帮助编译器标记函数参数int memcmp(const void * const s1, const void * const s2, size_t const n);的原因是,从函数的角度来看,函数参数只是一个局部变量。只要该函数不采用其地址,编译器就很容易看到该变量永远不会被修改。

相比之下,属于const原型的const修饰符(memcmp())  它是合同的一部分:它们表示该函数不会修改指向的数据。 const void *s1修饰符从不以这种方式用于参数本身,因为调用者不关心函数是否修改其参数:它们只是副本(因为C使用call-by-value)。

答案 1 :(得分:4)

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

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 );

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

答案 2 :(得分:0)

这是图书馆一致性的主要原因。将size_t参数更改为const size_t将需要修改大小的库被重写。并非所有库的实现都需要使用相同的算法。这是现有库函数未被调整的主要原因。

通常使用非const参数有目的地创建新的库函数,以便某些依赖于机器的实现可以使用可修改的参数。

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