Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
const关键字的用法_C_Optimization_Gcc_Constants_C99 - Fatal编程技术网

const关键字的用法

const关键字的用法,c,optimization,gcc,constants,c99,C,Optimization,Gcc,Constants,C99,我知道对函数参数使用const关键字可以提供更好的性能,但我总是忘记添加它。在这种情况下,编译器GCC是否足够聪明,可以注意到变量在函数执行过程中从未改变,并将其编译为我会显式添加const?您对const有一个常见的误解。仅使一个对象为常量意味着它的值永远不会改变,而且它不只是在函数期间,它永远不会改变 为函数const设置一个参数并不意味着它的值永远不会改变,它只是意味着函数不能改变值。该值可以通过其他方式更改 例如,看看这个函数: void f(const int* x, int* y)

我知道对函数参数使用const关键字可以提供更好的性能,但我总是忘记添加它。在这种情况下,编译器GCC是否足够聪明,可以注意到变量在函数执行过程中从未改变,并将其编译为我会显式添加const?

您对const有一个常见的误解。仅使一个对象为常量意味着它的值永远不会改变,而且它不只是在函数期间,它永远不会改变

为函数const设置一个参数并不意味着它的值永远不会改变,它只是意味着函数不能改变值。该值可以通过其他方式更改

例如,看看这个函数:

void f(const int* x, int* y)
{
    cout << "x = " << *x << endl;
    *y = 5;
    cout << "x = " << *x << endl;
}
现在,f有一个常量指针,但它指向一个非常量对象。因此该值可以更改,因为y是指向同一对象的非常量指针。所有这些都是完美的法律规范。这里没有什么有趣的事

因此,您的问题实际上没有答案,因为它完全基于错误的前提。

const与inline非常相似,只是编译器的提示,不能保证任何性能提升。const更重要的任务是保护程序员不受自己的影响,这样他们就不会不愿意修改不应该修改的变量。

1实际上,const不会直接影响您的性能。在某些情况下,它可能会使分析变得更简单,所以更喜欢const char*而不是char*,但const更多的是关于代码的语义和可读性


<> 2 CV合格类型在C和C++中形成不同类型。因此,即使您的编译器从使用默认常量中获益,也不会这样做,因为它将更改类型,并可能导致异常奇怪的事情。

作为优化的一部分,编译器将深入研究何时读取或写入内存位置。因此,编译器非常擅长检测变量何时未更改以及何时更改。当变量为常量时,优化器不需要您告诉他

然而,在适当的时候,您应该始终使用const。为什么?因为它使界面更清晰,更容易理解。当您更改不想更改的变量时,它可以帮助您检测错误

在这种情况下,编译器GCC是否足够聪明,能够注意到 variabele在函数执行期间从不更改,并将其编译为 会显式添加常量吗

不一定。例如:

void some_function(int *ptr); // defined in another translation unit

int foo(int a) {
    some_function(&a);
    return a + 1;
}
编译器看不到某些函数的功能,因此不能假设它不会修改

链接时间优化可能会看到某个函数真正做了什么,并相应地采取行动,但是就这个答案而言,我只考虑某些函数的定义不可用的优化。

int bar(const int a) {
    some_function((int*)&a);
    return a + 1;
}
编译器看不到某个函数的作用,但它可以假定a的值无论如何都不会改变。因此,它可以进行任何适用的优化:也许它可以在调用某个函数的过程中在被调用方保存一个寄存器;也许它在进行调用之前而不是之后计算返回值,然后将a。如果某个_函数修改了a,则程序具有未定义的行为,因此一旦发生这种情况,从编译器的POV来看,它对a使用的值是正确的还是错误的并不重要

因此,在本例中,通过标记一个常量,您告诉了编译器一些它无法知道的事情——某些函数不会修改*ptr。或者无论如何,如果它确实修改了它,那么您就不在乎程序的行为是什么

int baz(int a) {
    some_function(NULL);
    return a + 1;
}
在这里,编译器可以看到与标准相关的所有相关代码。它不知道某些_函数做什么,但它知道它没有任何标准的方法来访问a。因此,标记为const与否应该没有区别,因为编译器知道它无论如何都不会改变

当然,调试器支持会使这种情况复杂化——我不知道gcc和gdb的情况如何,但至少在理论上,如果编译器希望支持您使用调试器并手动修改,那么它可能不会将其视为不可修改。这同样适用于某些_函数使用特定于平台的功能在堆栈中穿行,并处理一个问题的可能性。平台不必提供这样的功能,但如果提供了,就会与优化冲突

我见过一个旧版本的gcc 3.x,不记得x没有进行某些优化,我没有进行局部int变量const,但在我的例子中,gcc 4确实进行了优化。无论如何,我想的不是一个参数,而是一个自动变量,用一个常量值初始化

在我所说的任何内容中,作为一个参数没有什么特别之处——它也可以是函数中定义的任何自动变量。请注意,要使参数获得使用常量值初始化的效果,唯一的方法是使用常量值调用函数,然后
r编译器以观察该调用的值。只有当函数内联时,才会发生这种情况。因此,对函数的内联调用可以对其应用额外的优化,这些优化是越界函数体不符合的。

如果启用某些优化标志,则可能会出现这种情况。参考GCC手册。我不确定编译器在优化时有多少地方可以真正利用const…我知道在函数参数上使用const关键字可以提供更好的性能,我当然不知道,但这可能只是我被误导了。@ChristianRau:提供更好的性能是一个大胆的主张,你有理由怀疑它,但它在某些情况下实现了某些优化。我在考虑按值传递的参数。当功能无法更改它们时,似乎没有其他可能更改它们。你是对的,当传递指针时,事情可能会不同。@Joshua:在这种情况下,对象实际上是常量,这是一个承诺,它的值永远不会改变。一般来说,编译器无法理解这一点,因为即使您只调用const函数,而不是非const对象,编译器也不能假定值不会更改,并且编译器通常无法查看您调用的每个函数。如果可以的话,那么它可以自己解决这个问题。但它不能假设所有常量函数都不修改值。如果对象是非常态,它们是允许的。你的回答和评论好像是关于C++的,但是这个问题不是关于C吗?你们都是对的!很抱歉,我无法删除此答案,因为它已被接受。您可以通过更改对指针的引用使此答案应用于C。然后,您将讨论通过指针传递到const的参数,这是在函数参数上使用const关键字的一种方法,但不是唯一的方法。哇,非常彻底地处理了这些问题。
int baz(int a) {
    some_function(NULL);
    return a + 1;
}