slightly cleaner strlen, also seems to compile to better code
authorRich Felker <dalias@aerifal.cx>
Thu, 27 Sep 2012 20:56:33 +0000 (16:56 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 27 Sep 2012 20:56:33 +0000 (16:56 -0400)
testing with gcc 4.6.3 on x86, -Os, the old version does a duplicate
null byte check after the first loop. this is purely the compiler
being stupid, but the old code was also stupid and unintuitive in how
it expressed the check.

src/string/strlen.c

index 936fb5cf56da2d00f3947d0aed2644a9397daef8..d6f8631d59dd1ba47334d955fc1fe6e94106dcf3 100644 (file)
@@ -3,7 +3,7 @@
 #include <stdint.h>
 #include <limits.h>
 
-#define ALIGN (sizeof(size_t)-1)
+#define ALIGN (sizeof(size_t))
 #define ONES ((size_t)-1/UCHAR_MAX)
 #define HIGHS (ONES * (UCHAR_MAX/2+1))
 #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
@@ -12,10 +12,8 @@ size_t strlen(const char *s)
 {
        const char *a = s;
        const size_t *w;
-       for (; ((uintptr_t)s & ALIGN) && *s; s++);
-       if (*s) {
-               for (w = (const void *)s; !HASZERO(*w); w++);
-               for (s = (const void *)w; *s; s++);
-       }
+       for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
+       for (w = (const void *)s; !HASZERO(*w); w++);
+       for (s = (const void *)w; *s; s++);
        return s-a;
 }