比std::strlen()更牛的strlen(),C语言版;

iamnobody 2011-08-26 08:17:02
是不是遇到过std::strlen()被自作多情的编译器“优化”成简单的循环?

下面是 1987-04-27 的一个大牛的作品: #define hasNulByte(x) ((x - 0x01010101) & ~x & 0x80808080)
的应用:

算法比std::strlen()更快一点,而且std::strlen()有个小缺陷:关于 char bug = 0x80; 看过的人懂的。


在release 模式会被内联优化成很棒的代码哦亲:



#define hasNulByte(x) ((x - 0x01010101) & ~x & 0x80808080)
#define SW (sizeof (int) / sizeof (char))

int xstrlen (const char *s) {
const char *p;
int d;

p = s - 1;
do {
p++;
if ((((int) p) & (SW - 1)) == 0) {
do {
d = *((int *) p);
p += SW;
} while (!hasNulByte (d));
p -= SW;
}
} while (*p != 0);
return p - s;
}


...全文
1032 62 打赏 收藏 转发到动态 举报
写回复
用AI写文章
62 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamnobody 2011-08-28
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 dic_008 的回复:]
楼主的帖精彩,其实很多时候是来看回帖的^.^
[/Quote]

谢谢捧场,,我想你应该会对这个感兴趣,我就是从那里找到这个的
http://bbs.pediy.com/showthread.php?t=133162
天亮后说晚安 2011-08-27
  • 打赏
  • 举报
回复
gmail
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 zhangsongcui 的回复:]

自己写了一段
C/C++ code
size_t myStrlen(const char* str)
{
const char* start = str;
__m128i m = _mm_load_si128((const __m128i*)str), zero = _mm_setzero_si128();
size_t pos;
for (pos = 0; ……
[/Quote]
#pragma function(string) //@_@
把全部代码扔上来好了
http://pastebin.com/rA0JHKje
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
自己写了一段
size_t myStrlen(const char* str)
{
const char* start = str;
__m128i m = _mm_load_si128((const __m128i*)str), zero = _mm_setzero_si128();
size_t pos;
for (pos = 0; !(pos = _mm_movemask_epi8(_mm_cmpeq_epi8(m, zero))); str += 16, m = _mm_load_si128((const __m128i*)str));
for (; (pos & 1) != 1; pos >>= 1, ++str);
return str - start;
}

注意跟strlen比速度时先#pragma intrinsic(strlen)
dic_008 2011-08-27
  • 打赏
  • 举报
回复
楼主的帖精彩,其实很多时候是来看回帖的^.^
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 58 楼 zhangsongcui 的回复:]
指令集这东西浅层次自学一些很容易
http://tieba.baidu.com/p/980788243?pn=1&v=1
[/Quote]

差点走神了,我应该学算法的,这个东西知道下就好,。。。
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
指令集这东西浅层次自学一些很容易
http://tieba.baidu.com/p/980788243?pn=1&v=1
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 55 楼 mingliang1212 的回复:]
引用 53 楼 zhangsongcui 的回复:
128位反不下啊


唉,太多不懂了。。。
[/Quote]

我看了下那批函数,大概懂了,因为没有能返回bool类型的函数。
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 55 楼 mingliang1212 的回复:]

引用 53 楼 zhangsongcui 的回复:
128位反不下啊


唉,太多不懂了。。。
[/Quote]
打错字了,“放”不下
基本资料MSDN都有
http://msdn.microsoft.com/zh-cn/library/kcwz153a.aspx
写代码时先找有没有对应的函数,找到就直接用,找不到就自己编。就是这样
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 53 楼 zhangsongcui 的回复:]
128位反不下啊
[/Quote]

唉,太多不懂了。。。
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 53 楼 zhangsongcui 的回复:]
引用 52 楼 mingliang1212 的回复:

引用 50 楼 zhangsongcui 的回复:
引用 48 楼 mingliang1212 的回复:

引用 44 楼 zhangsongcui 的回复:
_mm_cmpeq_epi8是分别比较16个char,相等则置返回值对应的byte为FF,不等置0

引用 37 楼

根据你写的代码,应该是将对应的BIT位置为1……
[/Quote]
你是说128位比较不能改变标志register?
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 52 楼 mingliang1212 的回复:]

引用 50 楼 zhangsongcui 的回复:
引用 48 楼 mingliang1212 的回复:

引用 44 楼 zhangsongcui 的回复:
_mm_cmpeq_epi8是分别比较16个char,相等则置返回值对应的byte为FF,不等置0

引用 37 楼

根据你写的代码,应该是将对应的BIT位置为1吧


_mm_cmpeq_epi8是置FF,_mm……
[/Quote]128位反不下啊
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 50 楼 zhangsongcui 的回复:]
引用 48 楼 mingliang1212 的回复:

引用 44 楼 zhangsongcui 的回复:
_mm_cmpeq_epi8是分别比较16个char,相等则置返回值对应的byte为FF,不等置0

引用 37 楼

根据你写的代码,应该是将对应的BIT位置为1吧


_mm_cmpeq_epi8是置FF,_mm_movemask_epi8是提取最高位放入int。
[/Quote]

为什么不直接比较 mm_cmpeq_epi8 返回值和 -1呢??
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 45 楼 mingliang1212 的回复:]

引用 44 楼 zhangsongcui 的回复:
引用 41 楼 mingliang1212 的回复:

引用 37 楼 zhangsongcui 的回复:
引用 36 楼 zhangsongcui 的回复:

自己写了一段
C/C++ code
size_t myStrlen(const char* str)
{
const char* start = str;
__m……
[/Quote]
那行循环右移很不河蟹哈……
zhangsongcui 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 mingliang1212 的回复:]

引用 44 楼 zhangsongcui 的回复:
_mm_cmpeq_epi8是分别比较16个char,相等则置返回值对应的byte为FF,不等置0

引用 37 楼

根据你写的代码,应该是将对应的BIT位置为1吧
[/Quote]

_mm_cmpeq_epi8是置FF,_mm_movemask_epi8是提取最高位放入int。
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 47 楼 qq602828308 的回复:]
怎么你们都用C++呢?
[/Quote]


不用不知道,用了吓一跳
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 zhangsongcui 的回复:]
_mm_cmpeq_epi8是分别比较16个char,相等则置返回值对应的byte为FF,不等置0

引用 37 楼 [/Quote]

根据你写的代码,应该是将对应的BIT位置为1吧
qq602828308 2011-08-27
  • 打赏
  • 举报
回复
怎么你们都用C++呢?
大V雪 2011-08-27
  • 打赏
  • 举报
回复
真不懂!
iamnobody 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 zhangsongcui 的回复:]
引用 41 楼 mingliang1212 的回复:

引用 37 楼 zhangsongcui 的回复:
引用 36 楼 zhangsongcui 的回复:

自己写了一段
C/C++ code
size_t myStrlen(const char* str)
{
const char* start = str;
__m128i m = _mm_load_si128((con……
[/Quote]


哇,好神奇啊
加载更多回复(41)

64,656

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧