C程序优化之路(二)

本文讲述在编写C程序代码的常用优化办法,分为I/O篇,内存篇,算法篇,MMX汇编篇。

二.内存篇

       在上一篇中我们讲述了如何优化文件的读写,这一篇则主要讲述对内存操作的优化,主要有数组的寻址,指针链表等,还有一些实用技巧。

I.优化数组的寻址

       在编写程序时,我们常常使用一个一维数组a[M×N]来模拟二维数组a[N][M],这个时候访问a[]一维数组的时候:我们经常是这样写a[j×M+i](对于a[j][i])。这样写当然是无可置疑的,但是显然每个寻址语句j×M+i都要进行一次乘法运算。现在再让我们看看二维数值的寻址,说到这里我们不得不深入到C编译器在申请二维数组和一维数组的内部细节上――实际在申请二位数组和一维数组,编译器的处理是不一样的,申请一个a[N][M]的数组要比申请一个a[M×N]的数组占用的空间大!二维数组的结构是分为两部分的:

① 是一个指针数组,存储的是每一行的起始地址,这也就是为什么在a[N][M]中,a[j]是一个指针而不是a[j][0]数据的原因。

② 是真正的M×N的连续数据块,这解释了为什么一个二维数组可以象一维数组那样寻址的原因。(即a[j][i]等同于(a[0])[j×M+i])

清楚了这些,我们就可以知道二维数组要比(模拟该二维数组的)一维数组寻址效率高。因为a[j][i]的寻址仅仅是访问指针数组得到j行的地址,然后再+i,是没有乘法运算的!

    所以,在处理一维数组的时候,我们常常采用下面的优化办法:(伪码例子)

    int a[M*N];
    int *b=a;
    for(…)
    {
        b[…]=…;
        …………
        b[…]=…;
        b+=M;
    }

这个是遍历访问数组的一个优化例子,每次b+=M就使得b更新为下一行的头指针。当然如果你愿意的话,可以自己定义一个数组指针来存储每一行的起始地址。然后按照二维数组的寻址办法来处理一维数组。不过,在这里我建议你干脆就直接申请一个二维数组比较的好。下面是动态申请和释放一个二维数组的C代码。

int get_mem2Dint(int ***array2D, int rows, int columns)     //h.263源代码
{
    int i;

    if((*array2D = (int**)calloc(rows, sizeof(int*))) == NULL) no_mem_exit(1);
    if(((*array2D)[0] = (int* )calloc(rows*columns,sizeof(int ))) == NULL) no_mem_exit(1);

for(i=1 ; i<rows ; i++)
        (*array2D)[i] =  (*array2D)[i-1] + columns  ;

return rows*columns*sizeof(int);
}

void free_mem2D(byte **array2D)
{
    if (array2D)
    {
        if (array2D[0])
            free (array2D[0]);
        else
            error ("free_mem2D: trying to free unused memory",100);

        free (array2D);
    }
    else
    {
        error ("free_mem2D: trying to free unused memory",100);
    }
}

顺便说一下,如果你的数组寻址有一个偏移量的话,不要写为a[x+offset],而应该为 b=a+offset,然后访问b[x]。

不过,如果你不是处理对速度有特别要求的程序的话,这样的优化也就不必要了。记住,如果编普通程序的话,可读性和可移值性是第一位的。

II.从负数开始的数组

       在编程的时候,你是不是经常要处理边界问题呢?在处理边界问题的时候,经常下标是从负数开始的,通常我们的处理是将边界处理分离出来,单独用额外的代码写。那么当你知道如何使用从负数开始的数组的时候,边界处理就方便多了。下面是静态使用一个从-1开始的数组:

int a[M];

int *pa=a+1;

现在如果你使用pa访问a的时候就是从-1M2了,就是这么简单。(如果你动态申请a的话,freea)可不要freepa)因为pa不是数组的头地址)

III.我们需要链表吗

       相信大家在学习《数据结构》的时候,对链表是相当熟悉了,所以我看有人在编写一些耗时算法的时候,也采用了链表的形式。这样编写当然对内存的占用(似乎)少了,可是速度呢?如果你测试:申请并遍历10000个元素链表的时间与遍历相同元素的数组的时间,你就会发现时间相差了百倍!(以前测试过一个算法,用链表是1分钟,用数组是4秒钟)。所以这里我的建议是:在编写耗时大的代码时,尽可能不要采用链表!

       其实实际上采用链表并不能真正节省内存,在编写很多算法的时候,我们是知道要占用多少内存的(至少也知道个大概),那么与其用链表一点点的消耗内存,不如用数组一步就把内存占用。采用链表的形式一定是在元素比较少,或者该部分基本不耗时的情况下。

(我估计链表主要慢是慢在它是一步步申请内存的,如果能够象数组一样分配一个大内存块的话,应该也不怎么耗时,这个没有具体测试过。仅仅是猜想 :P)

转载于:https://www.cnblogs.com/huaping-audio/archive/2008/09/11/1289454.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

long 对应oracle,【转】oracle number与java中long、int的对应

C&num; base 64图片编码解码使用WinForm实现了图片base64编码解码的 效果图: 示例base 64编码字符串: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKD ...MyBatis知多少(8)关系型数据库MyBatis的存在就是为了简化对关系数据库的访问.数据库的确非常复杂,要正确地使…

应用内moniter

通过dotnet-counter moniter可以在应用外部启动监控应用&#xff0c;当然也可以在进程内来来进行监控指标的收集或展示。进程内监控的好处是不用启用多个服务来完成监控和服务的分离&#xff0c;只要应用启动&#xff0c;监控指标也就产生&#xff0c;是紧密关系。class Progra…

史上最具争议的博弈游戏,我用概率论、博弈论找到了答案

全世界只有3.14 % 的人关注了青少年数学之旅要说最近人气最火热的游戏&#xff0c;莫过于前段时间刚崛起的“多多自走棋”。而关于“多多自走棋 ”被讨论得最多的就是&#xff0c;“到底是靠运气还是技术?”都说吃鸡靠运气&#xff0c;但这些道具加成&#xff0c;在数学计算面…

并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题

boost的mutex&#xff0c;condition_variable非常好用。但是在Linux上&#xff0c;boost实际上做的是对pthread_mutex_t和pthread_cond_t的一系列的封装。因此通过对原生态的POSIX 的mutex&#xff0c;cond的生成者&#xff0c;消费者的实现&#xff0c;我们可以再次体会boost带…

送给销售一族

投身销售英勇无畏工作行业看似高贵其实生活极其琐碎为了生计吃苦受累鞍前马后终日疲惫客人投诉照死赔罪点头哈腰就差下跪日不能息夜不能寐老板一叫立即到位一年到头加a班受罪劳动法规统统作废身心交瘁暗自流泪屁大点事反复开会逢年过节家人难会分分秒秒不敢离位迎接审核让人崩溃…

akka linux 端口,Actor模型开发库 Akka

Akka 是一个用 Scala 编写的库&#xff0c;用于简化编写容错的、高可伸缩性的 Java 和 Scala 的 Actor 模型应用。Actor模型并非什么新鲜事物&#xff0c;它由Carl Hewitt于上世纪70年代早期提出&#xff0c;目的是为了解决分布式编程中一系列的编程问题。其特点如下&#xff1…

简单粗暴的肢体语言解读攻略 | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源网络&#xff0c;侵权删&#xff09;

基于事件驱动架构构建微服务第1部分:应用程序特定的业务规则

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part1-application-specific-business-rules/如今&#xff0c;洋葱或六边形等架构为代码的可测试性和维护、与外部框架的独立性提供了重要帮助。在本教程中&#xff0c;我…

WinhexV13.2汉化版

WinhexV13.2sr-11_H.rar转载于:https://blog.51cto.com/www520/16874

JavaWeb 项目启动时,后台开启一个线程的方法

原文链接&#xff1a;http://blog.csdn.net/it_wangxiangpan/article/details/7168286JavaWeb 服务启动时&#xff0c;在后台启动加载一个线程。目前&#xff0c;我所掌握的一共有两种方法&#xff0c;第一种是监听&#xff08;Listener&#xff09;&#xff0c;第二种是配置随…

linux脚本 逻辑运算,Linux-shell-逻辑运算和;

7.Shell7.5.2命令执行的判断依据&#xff1a; ; , &&, ||1.cmd ; cmd (不考虑指令相关性的连续指令下达)一般用于多条命令之间没有直接需求联系&#xff0c;最多只是有一个执行先后的关系。[rootlocalhost tmp]# sync; shutdown -h now2.与&&或 ||指令下达情况…

我居然从一只猫身上学到了斐波那契数列

猫的数学这么好是有原因的斐波那契数列&#xff08;Fibonacci sequence&#xff09;是由数学家列昂纳多斐波那契定义的把它写成数列的形式是这样的&#xff1a;1,1,2,3,5,8,13,21,34,55,89,...比如&#xff1a;人的耳朵比如&#xff1a;台风比如&#xff1a;松果的底部螺纹从两…

听说过Netflix的Chaos Monkey吗?不用羡慕,我们.NET也有

Chaos Monkey&#xff0c;是Netflix工程师创建的一种故障注入系统&#xff0c;它会随机在生产实例中引发各种各样的故障或异常&#xff0c;以确保它们的系统能够在这样的情况下存活&#xff0c;而不会对客户造成任何影响。可见&#xff0c;Chaos Monkey可以提高系统的安全和可用…

(ZT)VC++的链接错误LNK2001

学习VC&#xff0b;&#xff0b;时经常会遇到链接错误LNK2001&#xff0c;该错误非常讨厌&#xff0c;因为对于编程者来说&#xff0c;最好改的错误莫过于编译错误&#xff0c;而一般说来发生连接错误时&#xff0c;编译都已通过。产生连接错误的原因非常多&#xff0c;尤其LNK…

PHP中session与cookie的简单使用

2019独角兽企业重金招聘Python工程师标准>>> cookie简单实例&#xff1a; <?php if($_GET[out]){ //注销cookie setcookie(id,); setcookie(password,); echo "<script>location.hrefcookie.php</script>"; …

linux下安装服务,linux下的软件服务安装管理

在centos7下&#xff0c;为系统装一个服务有两种方式&#xff0c;一种是通过系统提供的rpm/yum自动安装&#xff0c;一种是通过服务的官网提供的安装包进行安装。rpm/yum 服务的安装及管理yum -y install 包名: 可以通过yum方式默认安装当前yum源中提供的软件服务&#xff0c;y…

NetBeans Weekly News 刊号 # 27 - Sep 24, 2008

刊号 # 27 - Sep 24, 2008 日程表 注册 NetBeans Day--圣保罗&#xff0c;巴西&#xff08;十月一日&#xff09; 欢迎来到巴西圣保罗的 Sun Tech Days 。赶快在十月一日加入我们的 NetBeans Deep Dive 吧&#xff01;注册 NetBeans Day 是免费的&#xff0c;即使您不参加 Sun …

做项目开发你必须得掌握的知识:设计模式

先分享一个小故事 两个年轻人是大学同班同学&#xff0c;毕业后被同一家公司录取&#xff0c;可以说是站在相同的起跑线上。两人对未来也都是信心满满&#xff0c;踌躇满志。其中一人怀抱满腔激情&#xff0c;到处学习热门框架&#xff0c;但受限于公司体量和业务逻辑&#xff…

985硕博士:你为什么比我差?

全世界只有3.14 % 的人关注了青少年数学之旅身边总有些人看上去很轻松&#xff0c;不仅在工作中游刃有余&#xff0c;还知识渊博&#xff0c;对各种事情有自己的思考。这次&#xff0c;我们非常认真地筛选了这些公众号&#xff0c;他们专注于内容&#xff0c;关心当下发生的事情…

熊猫烧香是天才作品吗?

今天在新闻中看到有关武男的消息&#xff0c;很不幸&#xff0c;再次发现媒体称武男——李俊为天才。这年头&#xff0c;程序员队伍已经非常壮大了&#xff0c;称得上天才作品的有哪些呢&#xff1f;从我自己的角度列举一下&#xff0c;当然不止这些。字处理&#xff1a;WPS DO…