C++中字母大写和小写转换实现的优化

write by 九天雁翎(JTianLing) --
blog.csdn.net/vagrxie

讨论新闻组及文件

在本文中所有以转换为小写为例。

从推荐复用代码的角度来看,用库函数是不错的办法:

方案一:

char gc1[53] = "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";

void wayOne()

{

strlwr(gc1);

}

长处是使用方便,别人看着也easy理解,可是效率慢的让人吐血。

extern "C" char * __cdecl _strlwr (

char * string

)

{

if (__locale_changed == 0)

{

char * cp;

/* validation
section */

_VALIDATE_RETURN(string != NULL,
EINVAL, NULL);

for (cp=string; *cp; ++cp)

{

if
('A' <= *cp
&& *cp <= 'Z')

*cp
+= 'a' - 'A';

}

return(string);

}

else

{

_strlwr_s_l(string, (size_t)(-1),
NULL);

return string;

}

}

循环中平均2.5次的推断,(*cp一次,if的’A’<=一次,*cp<=版次)加平均每次0.5次的加法,尽管这种转换O(n)是不可缺少的,可是对于这样多的操作还是慢的可怕。

例2:

char gc2[53]
= "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";

namespace MYTEST

{

inline char*
strlwr(char
*asz)

{

for(char*
lp = gc2;
*lp != 0; ++lp)

{

*lp |= 0x20;

}

return asz;

}

}

void wayTwo()

{

MYTEST::strlwr(gc2);

}

此例中利用了ASCII字母值的特点,一共仅仅有一次推断(*lp!=0),一次位或操作。算法上提高了非常多:)事实上已经达到了1/3的效率提升。。。。。

将原来一大堆的代码,转化成了反汇编仅仅有4句的程序:

00401020 80 08 20         or          byte ptr [eax],20h

00401023 83 C0 01         add         eax,1

00401026 80 38 00         cmp         byte ptr [eax],0

00401029 75 F5            jne         wayTwo+10h (401020h)

可是考虑到char仅仅是1个字节,看到

00401020 80 08 20         or          byte ptr [eax],20h

一句都感觉不爽,白白浪费了eax 这样4个字节的寄存器,于是能够这样优化:

namespace MYTEST2

{

inline char*
strlwr(char
*asz)

{

long* lp
= (long*)gc3;

for(; *((char*)lp) != 0; ++lp)

{

(long)(*lp) |= 0x20202020;

}

for(char*
lpc = (char*)lp;*lpc!=0; ++lpc)

{

*lpc |= 0x20;

}

return asz;

}

}

说实话,。。。。。。。。。。。没有不论什么清晰性可言,没有不论什么可读性可言,可是优化的思想就是充分的利用4个字节的寄存器,而且以DWORD来读取内存,这是非常有效率的方式。汇编代码事实上比C语言代码更加清晰,原因在于C语言代码还须要处理大量与类型相关的事情,汇编代码不须要。

第一个循环汇编代码例如以下:

00401040 81 08 20 20 20 20 or          dword ptr [eax],20202020h

00401046 83 C0 04         add         eax,4

00401049 80 38 00         cmp         byte ptr [eax],0

0040104C 75 F2            jne         wayThree+10h (401040h)

将循环次数降低了3/4。。。。所以效率的优化还是非常明显的。单指令多数据操作的思想只是就是这样的思想的延生罢了。。。呵呵,可是说在前面,如此影响可读性的效率优化,除非在非常必要的情况下,不然慎用。。。。。

为了证实效率的优化,起码也得给出一个測试结果给大家看看吧,不然还以为我胡扯了。

void wayOne()

// Hit Count          : 1

// Time               : 5553.00

// Time with Children : 5553.00

{

strlwr(gc1);

}

void wayTwo()

// Hit Count          : 1

// Time               : 247.00

// Time with Children : 247.00

{

MYTEST::strlwr(gc2);

}

void wayThree()

// Hit Count          : 1

// Time               : 180.00

// Time with Children : 180.00

{

MYTEST2::strlwr(gc3);

}

int _tmain(int argc, _TCHAR* argv[])

// Hit Count          : 1

// Time               : 6836996435.00

// Time with Children : 6837002415.00

{

wayThree();

wayTwo();

wayOne();

}

測试结果为AQtime5測试数据,单位为机器周期,由于结果已经非常明显了,所以没有进行多次循环的測试。而且为了排除缓存的影响,将最快的放在了最前面,那么哪怕有缓存的影响,对于wayThree也是最不利的才对。库函数的5000多的结果,说慢的可怕并不为过。在数据量非常大的时候,这样的优化的差异可不是一点点而已。

write by 九天雁翎(JTianLing)
-- blog.csdn.net/vagrxie

最新文章

  1. WIZnet官方网盘
  2. Javascript基础系列之(五)条件语句(比较操作符)
  3. SpringMVC配置easyui-datagrid
  4. VS/Visual studio 源代码编辑器里的空处出现点号解决办法
  5. 使用C#通过Thrift访问HBase
  6. Binding to the Most Recent Visual Studio Libraries--说的很详细,很清楚
  7. C#字符串拼接怎么转义背景图片
  8. 解决Matlab启动时 &quot; Can&#39;t check 9.0 VCRTs The application has failed to start because……&quot; 的错误
  9. Spring MVC控制器用@ResponseBody声明返回json数据报406的问题
  10. C# DES加解密
  11. Java内部类的使用小结
  12. Exiting the Matrix: Introducing Metasploit&#39;s Hardware Bridge
  13. Vue 项目实战系列 (一)
  14. winform WebBrowser控件中,cs后台代码执行动态生成的js
  15. nmap命令总结
  16. mesh函数
  17. Python swapcase
  18. scrapy 也能爬取妹子图?
  19. tpshop购物网站价格筛选功能的测试用例设计
  20. android项目中的拍照和本地图片截图

热门文章

  1. 17.1.1 How to Set Up Replication
  2. 用 Python 测试框架简化测试
  3. TCP三次握手和四次挥手具体解释
  4. 使用ant的jar任务打jar包
  5. Creating Spatial Indexes(mysql 创建空间索引 The used table type doesn&#39;t support SPATIAL indexes)
  6. css概述
  7. android开发之蓝牙配对连接的方法
  8. France &#39;98
  9. attachEvent和addEventListener详解
  10. 基于visual Studio2013解决面试题之0510连续数之和