在频繁打开的块范围{}中声明自动变量时,效率会降低吗?

时间:2019-06-10 19:27:50

标签: c scope compiler-optimization lifetime

在K&R中指出:

  

在块中声明和初始化的自动变量是   每次进入该块时都会初始化。

这里是仅用于传达问题的代码段。显示了两个选项;在主体函数体中声明error_string,并在if()的块范围内声明它。

问题是,如果使用了option2声明,是否可以依靠编译器来优化重复实例化字符串的行为?

声明变量最接近使用它们的位置可能会使代码更具可读性。尽可能限制它们的范围也许是一种好的设计实践。这样做会对效率产生明显的损害吗?

#define MAX_ERROR_STRING_LEN 1024

void process_results(int *results, int n_results)
{
    int i;
    char error_string[MAX_ERROR_STRING_LEN]; //option1

    for (i = 0; i < n_results; i++) //suppose n_results == 1 million, 98% "FAILURE"
    {
        if (results[i] == FAILURE)
        {
            char error_string[MAX_ERROR_STRING_LEN];//option2

            get_error_string(error_string, MAX_ERROR_STRING_LEN - 1);

            fprintf(debug_log, "Error: %s\n", error_string);
        }
    }
}

在相关说明中,应避免这种情况:

    for (i = 0; i < strlen(error_string); i++)
        printf("%c", error_string[i]);

赞成:

    int len = strlen(error_string);
    for (i = 0; i < len; i++)
        printf("%c", error_string[i]);

还是在依赖运行时数据的情况下进行优化?

编辑-仅添加研究就不会有任何变化:

认为这确认了重复创建和销毁了块范围变量(出于程序员的所有意图和目的):

  

A.4.1存储类别有两种存储类别:自动和存储。   静态的。几个关键字,以及对象的上下文   声明,指定其存储类。 自动对象在本地   一个区块(第9.3节),并在退出该区块时被丢弃。

其余大多数似乎是指词汇范围而不是链接:

  

A.11.1词法范围...函数参数的范围   定义从定义功能的块的开头开始,并且   通过功能持续存在;函数中参数的范围   声明在声明器的末尾结束。一个范围   在块的开头声明的标识符从其结尾开始   声明符,并持续到块的末尾。

关于词法范围?

  

名称范围是程序中名称所在的部分   可以使用。对于在a开头声明的自动变量   函数,作用域是在其中声明名称的函数。   不同功能中同名的局部变量无关。   函数的参数也是如此,它们位于   影响局部变量。

  

名称也具有作用域,这是程序所在的区域   它是已知的,还有一个链接,它确定   另一个范围是指相同的对象或功能。范围和联系   在A.11中进行了讨论。

1 个答案:

答案 0 :(得分:4)

未初始化局部变量error_string,使用块范围而不是函数范围声明它没有开销。某些编译器可能在进入块作用域时为error_string分配临时堆栈空间,并在离开该作用域时对其进行分配,这在两种情况下都涉及一条指令,但是大多数编译器会在一个步骤中为所有局部变量分配空间。函数的开始。

由于您担心效率,因此请注意,相比于此,发布来打印字符串的两个代码片段的效率都非常低:

    fputs(error_string, stdout);