auto
变量在运行时实例化,因此任何初始化也必须在运行时发生,这将产生一些性能损失-具体损失的程度取决于编译器和优化级别。
话虽如此,你的同事不应该在不做以下两个操作之一的情况下删除初始化:
编辑
例如,我将代码更改为将初始化程序定义为构建命令的一部分,然后使用clock
库函数进行了一些简单的仪器测量:
#include <stdio.h>
<strong>#include <time.h></strong>
void bar_read( int *array )
{
printf( "array[1]: %d\n", array[1] );
}
void bar_write( int *array )
{
array[1] = 1;
}
int main( void )
{
<strong>clock_t start = clock();</strong>
#ifndef FOO_SIZE
#define FOO_SIZE 2000
#endif
#ifndef INIT
#define INIT
#endif
int foo[FOO_SIZE] INIT ;
bar_read( foo );
bar_write( foo );
bar_read( foo );
<strong>clock_t end = clock();</strong>
printf( "operation took %lu clocks (%f seconds)\n", end-start, (double)(end-start)/CLOCKS_PER_SEC );
<strong>return (int)(end-start);</strong>
}
我可以进行带初始化和不带初始化的构建,看看运行所需时间是否有差异:
$ gcc -o init -std=c11 -pedantic -Wall -Werror -DFOO_SIZE=2000 -DINIT="" init.c
$ ./init
array[1]: -1898976766
array[1]: 1
operation took 39 clocks (0.000039 seconds)
$ gcc -o init -std=c11 -pedantic -Wall -Werror -DFOO_SIZE=2000 -DINIT="={0}" init.c
$ ./init
array[1]: 0
array[1]: 1
operation took 53 clocks (0.000053 seconds)
我让main
返回程序主要部分使用的时钟数。然后,我编写了一个shell脚本来构建带有和不带有数组初始化器的代码,运行每个版本100次(比我们需要的样本大,但运行时间不长),并对这些运行取平均值(整数平均值,但足以说明问题):
#!/bin/bash
INIT_PARAMS=( '""' '"={0}"' )
let runs=100
for INIT in "${INIT_PARAMS[@]}"
do
cmd="gcc -o init -std=c11 -pedantic -Wall -Werror -DFOO_SIZE=2000 -DINIT=${INIT} init.c"
echo $cmd
eval $cmd
let x=0
for i in `seq 1 1 $runs`
do
./init >/dev/null
let x=$x+$?
done
done
我得到的输出是:
$ . init_test.sh
gcc -o init -std=c11 -pedantic -Wall -Werror -DFOO_SIZE=2000 -DINIT="" init.c
Average clocks per run for INIT="" is 24
gcc -o init -std=c11 -pedantic -Wall -Werror -DFOO_SIZE=2000 -DINIT="={0}" init.c
Average clocks per run for INIT="={0}" is 33
因此,在声明的同时初始化一个包含2000个int
元素的数组会受到明显的惩罚,平均需要9个时钟周期(0.000009秒),增加了37%,并且没有进行任何优化。提高优化级别可以减少这种成本(可能),但无法完全消除它。
int foo[FOO_SIZE] = {0};
和int foo[FOO_SIZE];
之间的差异应在编译时解决。通常最好进行零初始化,因为编译器可能不会为您执行此操作。foo
是本地变量,因此它不会使用.bss
部分,而是将位于堆栈上,无论是否进行零初始化。虽然具体实现可能因编译器而异,但不应有任何显着的运行时性能影响。 - h0r53int foo[FOO_SIZE] = {0};
添加了运行时初始化,这会影响性能。我在一些架构上看到它被编译成某种内部memset
调用的变体。 - Eugene Sh.char buff [FOO_SIZE];
b)如果我使用该数组进行任何读取,并且必须确保变量以已知值开始,则会投资运行时初始化时间:char buff [FOO_SIZE] = {0};
- EmbeddedGuy