为什么在循环中评估 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.02920.027570.029460.02847。 对于 n = 20.030220.0280.029540.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 --.