将循环用函数包装,用时更少[更新]

本文探讨了一个有趣的编程现象:将循环放入单独函数并从main调用时,执行时间反而缩短。通过对比不同方法的执行时间及反编译后的汇编代码,揭示了背后的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看书用到了程序段计时器,顺便就写一小段的代码来玩玩,结果发现一个有趣的现象,将一个简单的循环从main函数移出,并包装到一个单独的函数,然后从main调用该函数,结果所使用的时间反而少了。按理来说,函数调用会涉及到多次的内存读写,应该是时间会延长,事实却相反。

小二,上代码!

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
struct timevale {
long tv_sec;
long tv_usec;
};
double getSum (int len){
int i = 0;
int sum = 0;
for(i = 0; i < len; i++){
sum += 1;
}
}

main (){
struct timevale starttime, endtime; //use gettimeofday();
clock_t beg, end; //use clock() to get time
int len = 10000000;
double sum = 0;
int sumInt = 0;
int i;
scanf("%d", &len); //get the length.

beg = clock();
for(i = 0; i < len; i++){
sum += 1;
}
end = clock();
double cost = (double)(end - beg) / CLOCKS_PER_SEC;
printf("sum %lf\n", sum);
printf("used time: %lf\n", cost);

printf("\n use function : \n ");
beg = clock();
getSum(len);
end = clock();
cost = (double)(end - beg) / CLOCKS_PER_SEC;
printf("sum %lf\n", sum);
printf("used time: %lf\n", cost);

gettimeofday(&starttime,0);
for(i = 0; i < len; i++){
sum += 1;
}
gettimeofday(&endtime,0);
double timeuse = 1000000*(endtime.tv_sec - starttime.tv_sec) + endtime.tv_usec - starttime.tv_usec;
printf("------------ \n used time: %lf\n", timeuse);


gettimeofday(&starttime,0);
getSum(len);
gettimeofday(&endtime,0);
timeuse = 1000000*(endtime.tv_sec - starttime.tv_sec) + endtime.tv_usec - starttime.tv_usec;
printf("------------ \n used time: %lf\n", timeuse);
}

结果:
# ./timeCost
100000000
sum 100000000.000000
used time: 0.370000 <---- for 循环 in main

use function :
sum 100000000.000000
used time: 0.230000 <---- 函数调用
------------
used time: 376234.000000 //微秒 <---- for 循环 in main
------------
used time: 225131.000000
#


========2014-01-17
以上代码有一点问题,在于main函数中定义了sum 为double,而函数中定义为int,因此导致了编译后,main中的for循环用到了浮点寄存器%xmm1等,导致了时间的增加。

将函数更新之后,问题就出现了,函数调用的时间还是比直接写在main里面的短:
# ./timeCost
700000000
sum 700000000
used time: 1.720000

use function :
used time: 1.580000
------------
used time: 1732559.000000
------------
used time with function: 1581448.000000

同时,反编译后得到的汇编代码中可以看到,main与getSum中的循环体是一样的:
0000000000400448 <getSum>:
400464: eb 08 jmp 40046e <getSum+0x26>
400466: 83 45 fc 01 addl $0x1,0xfffffffffffffffc(%rbp)
40046a: 83 45 f8 01 addl $0x1,0xfffffffffffffff8(%rbp)
40046e: 8b 45 f8 mov 0xfffffffffffffff8(%rbp),%eax
400471: 3b 45 ec cmp 0xffffffffffffffec(%rbp),%eax
400474: 7c f0 jl 400466 <getSum+0x1e>

0000000000400478 <main>:
400495: eb 08 jmp 40049f <main+0x27>
400497: 83 45 f8 01 addl $0x1,0xfffffffffffffff8(%rbp)
40049b: 83 45 fc 01 addl $0x1,0xfffffffffffffffc(%rbp)
40049f: 8b 45 fc mov 0xfffffffffffffffc(%rbp),%eax
4004a2: 3b 45 f4 cmp 0xfffffffffffffff4(%rbp),%eax
4004a5: 7c f0 jl 400497 <main+0x1f>


Then why????
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值