在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中进行了讨论。
答案 0 :(得分:4)
未初始化局部变量error_string
,使用块范围而不是函数范围声明它没有开销。某些编译器可能在进入块作用域时为error_string
分配临时堆栈空间,并在离开该作用域时对其进行分配,这在两种情况下都涉及一条指令,但是大多数编译器会在一个步骤中为所有局部变量分配空间。函数的开始。
由于您担心效率,因此请注意,相比于此,发布来打印字符串的两个代码片段的效率都非常低:
fputs(error_string, stdout);