为什么在循环中评估 sizeof 并不比对对象大小使用固定数字更快?
Why evaluating sizeof in a loop isn't faster than using a fixed number for the size of the object?
当谈到从文件写入和读取数据(变量和对象)时,我们的老师告诉我们这样做:
while(1){
if(fwrite(&object, sizeof object, 1, fp)!= 1){
break;
}
然而,这应该更快似乎是合乎逻辑的:
int num = sizeof object;
while(1){
if(fwrite(&object, num, 1, fp)!=1){
break;
}
毕竟,不会每次迭代都评估对象的大小。所以,我写了一个简单的程序来测试这个:
#include <stdio.h>
#include <stdlib.h>
struct block{
int val;
float mal; //the variables are irrelevant here
char *ch;
}object;
int main(void){
FILE *fp;
int f = sizeof object;
if((fp=fopen("file.bin", "wb"))==NULL){
puts("Unable to open file.");
exit(1);
}
int n = 2; //either set n to 1 or 2
switch(n){
case 1:
for(int i = 0; i <101; i++){
if(fwrite(&object, sizeof object, 1, fp)!=1){
puts("I/O error.");
break;
}
break;
}
case 2:
for(int i = 0; i <101; i++){
if(fwrite(&object, f, 1, fp)!=1){
puts("I/O error.");
break;
}
break;
}
}
puts("Fin.");
return 0;
}
然而,当我在 devc++ 中多次 运行 这个程序时,令我惊讶的是,时间基本上没有差异。
对于 n = 1
,我得到了这些时间:0.0292
、0.02757
、0.02946
、0.02847
。
对于 n = 2
:0.03022
、0.028
、0.02954
、0.02885
。
第二种选择并不快,而且似乎没有可区分的模式。给出了什么?
如果您检查中间编译结果,您会发现它们本质上是等价的。
使用 gcc
和 -fdump-tree-optimized
标志编译产生以下结果:
$ ls
speedtest.c
$ gcc -fdump-tree-optimized speedtest.c
$ ls
a.out speedtest.c speedtest.c.227t.optimized
如果您查看 *.optimized
文件,您会发现如下摘录:
对于int f = sizeof object;
:
f_9 = 16;
对于fwrite(&object, sizeof object, 1, fp)
:
_1 = fwrite (&object, 16, 1, fp_12);
对于 fwrite(&object, sizeof object, 1, fp)
,它利用了第一个摘录中的赋值:
_2 = (long unsigned int) f_9;
_3 = fwrite (&object, _2, 1, fp_12);
如您所见,sizeof
运算符正在编译时计算。
sizeof
运算符是 documented part of the C standard and is defined alongside other unary operators, such as ++
and --
.
当谈到从文件写入和读取数据(变量和对象)时,我们的老师告诉我们这样做:
while(1){
if(fwrite(&object, sizeof object, 1, fp)!= 1){
break;
}
然而,这应该更快似乎是合乎逻辑的:
int num = sizeof object;
while(1){
if(fwrite(&object, num, 1, fp)!=1){
break;
}
毕竟,不会每次迭代都评估对象的大小。所以,我写了一个简单的程序来测试这个:
#include <stdio.h>
#include <stdlib.h>
struct block{
int val;
float mal; //the variables are irrelevant here
char *ch;
}object;
int main(void){
FILE *fp;
int f = sizeof object;
if((fp=fopen("file.bin", "wb"))==NULL){
puts("Unable to open file.");
exit(1);
}
int n = 2; //either set n to 1 or 2
switch(n){
case 1:
for(int i = 0; i <101; i++){
if(fwrite(&object, sizeof object, 1, fp)!=1){
puts("I/O error.");
break;
}
break;
}
case 2:
for(int i = 0; i <101; i++){
if(fwrite(&object, f, 1, fp)!=1){
puts("I/O error.");
break;
}
break;
}
}
puts("Fin.");
return 0;
}
然而,当我在 devc++ 中多次 运行 这个程序时,令我惊讶的是,时间基本上没有差异。
对于 n = 1
,我得到了这些时间:0.0292
、0.02757
、0.02946
、0.02847
。
对于 n = 2
:0.03022
、0.028
、0.02954
、0.02885
。
第二种选择并不快,而且似乎没有可区分的模式。给出了什么?
如果您检查中间编译结果,您会发现它们本质上是等价的。
使用 gcc
和 -fdump-tree-optimized
标志编译产生以下结果:
$ ls
speedtest.c
$ gcc -fdump-tree-optimized speedtest.c
$ ls
a.out speedtest.c speedtest.c.227t.optimized
如果您查看 *.optimized
文件,您会发现如下摘录:
对于int f = sizeof object;
:
f_9 = 16;
对于fwrite(&object, sizeof object, 1, fp)
:
_1 = fwrite (&object, 16, 1, fp_12);
对于 fwrite(&object, sizeof object, 1, fp)
,它利用了第一个摘录中的赋值:
_2 = (long unsigned int) f_9;
_3 = fwrite (&object, _2, 1, fp_12);
如您所见,sizeof
运算符正在编译时计算。
sizeof
运算符是 documented part of the C standard and is defined alongside other unary operators, such as ++
and --
.