Почему оценка sizeof в цикле не быстрее, чем использование фиксированного числа для размера объекта? - PullRequest
0 голосов
/ 03 июня 2018

Когда речь идет о записи и чтении данных (переменных и объектов) из & в файлы, наш учитель сказал нам сделать это следующим образом:

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.Второй вариант не быстрее, и, похоже, нет различимого шаблона.Что дает?

1 Ответ

0 голосов
/ 04 июня 2018

Если вы проверите промежуточные результаты компиляции, вы увидите, насколько они по существу эквивалентны.

Компиляция с использованием 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 является документированной частью стандарта C и определен наряду с другими унарными операторами, такими как ++ и --.

.
...