字符串逆序输出,编译器优化,循环代码外提,无效代码删除

程序很简单

//将一个字符数组逆序输出

#include <stdio.h>
#include <string.h>

int main()
{
	char a[10] = "abcdefg";

	for (int i = strlen(a) - 1; i >= 0; i--)
	{
		printf("%c", a[i]);
	}
		
	return 0;
}

有人觉得需要将"循环代码外提”,避免重复执行strlen(a) - 1,从而提高程序运行效率,像下面这样。没错,CSAPP和编译原理都是这么说的。

#include <stdio.h>
#include <string.h>

int main()
{
	char a[10] = "abcdefg";

	int i = strlen(a) - 1;

	for (; i >= 0; i--)
	{
		printf("%c", a[i]);
	}
		
	return 0;
}

为了验证程序执行速度是不是真的提高了,重复执行一亿次。

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

int main()
{
	clock_t t1 = clock();

	char s[10] = "abcdefg";
	int x = 0;

	for (int n = 0; n < 100000000; n++)
	{
		for (int i = strlen(s) - 1; i >= 0; i--)
		{
			//printf("%c", s[i]);
			x = x + i;
		}
	}

	clock_t t2 = clock();
	cout << t2 - t1 << "毫秒" << endl;

	return 0;
}

为什么将printf语句注释掉了呢?输出是比较耗费时间的,为了测量程序真正的运行时间,IO语句要注释掉,加一条别的语句 x = x + i。运行结果如下:

C语言不愧是宇宙最快的语言之一,为了表示谦虚,加上“之一”二字。居然0毫秒就执行完了-_- 感觉不对啊,1亿好歹也是10的8次方呢?怎么0毫秒就完事了?要不把1亿次改成100亿试试? 不出意外的话,还是0毫秒。

看看汇编代码:

根本不见1亿的踪影?编译器的优化确实厉害,直接删除无效的代码,如果程序中的某些语句对输出没有影响,那么这些语句被视为无效代码 ,不执行。下面的代码加上一条输出x的语句,那么上述循环体的无效代码将变为有效代码。

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

int main()
{
	clock_t t1 = clock();

	char s[10] = "abcdefg";
	int x = 0;

	for (int n = 0; n < 100000000; n++)
	{
		for (int i = strlen(s) - 1; i >= 0; i--)
		{
			//printf("%c", s[i]);
			x = x + i;
		}
	}

	printf("%d\n", x);    //增加一条输出语句

	clock_t t2 = clock();
	cout << t2 - t1 << "毫秒" << endl;

	return 0;
}

运行结果如下:

 执行时间大概是0.1秒多,相当于10^8(10的8次方)纳秒,for循环体循环次数刚好也是10^8,掐指一算,每次循环的平均执行时间是1纳秒,仅仅相当于从L1 cache取一次数据的时间,C语言叠加宇宙第一IDE优化的BUF,果然快的离谱。

编译器优化代码的权限很大,大到可以删除无效代码、更改代码执行次序。“只要保证对最后的输出结果没有影响”。如果是编写多线程代码,编译器也能随意更改单个线程里的代码执行次序,噩梦^_^

再看看汇编代码,这次看到了一亿的身影。

说了半天,循环代码还没外提呢,外提之后,试试运行速度会不会加快?

 

大失所望,运行速度并没有加快,再次感谢编译器的优化(在宇宙第一IDE里写代码,随便写,很难写出执行效率很低的代码)。计算密集型的程序,程序代码全部搞定之后,运行时记得把工具栏下拉框里的debug改成release,有惊喜^_^

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值