# strlen in IOS
contributed by < [Eric Lin](https://github.com/ericlinsechs) >
## Overview
The technique used to detect `\0` character by [strlen](https://opensource.apple.com/source/Libc/Libc-583/arm/string/strlen.s) in IOS:
```
Laligned_loop:
/* ((x - 0x01010101) & ~x & 0x80808080) == hasnull(word) */
sub r3, r2, r1 /* x - 0x01010101 */
bic r3, r3, r2 /* above & ~x */
tst r3, r1, lsl #7 /* above & 0x80808080 */
ldreq r2, [r0], #4 /* load next word */
beq Laligned_loop
```
The same techique can be found in [string/strlen.c](https://github.com/eblot/newlib/blob/master/newlib/libc/string/strlen.c):
```c
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
/* Nonzero if X (a long int) contains a NULL byte. */
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
#else
#error long int is not a 32bit or 64bit type.
#endif
#endif
```
I am curious about why this code can detect NULL byte.
## Break down
First, simplify the code to detecting whether one byte data is NULL or not:
```c
(X - 0x01) & ~X & 0x80
```
Convert it according to [De Morgan's laws](https://en.wikipedia.org/wiki/De_Morgan%27s_laws):
```c
~(~(X - 0x01) | X) & 0x80
```
Switch the first two parameters' position:
```c
~(X | ~(X - 0x01)) & 0x80
```
Now, if `X = 0`:
```c
X = ~(X | ~(0b10000001)) & 0x80
```
```c
X = ~(0b00000000 | 0b01111110)) & 0x80
```
```c
X = 0b10000001 & 0b10000000
```
```c
X = 0x80
```
Other `X != 0` conditions:
* X = 1:
* ~(0x01 | 0xFFFFFFFFF) => 0x0 & 0x80 => 0
* X = 2 => 0000 0000 => 0
…
* X = 255 => 0000 0000 => 0
## Conclusion
* If `X = 0`, the outcome from `DETECTNULL(X)` will be `0x80`.
* If `X != 0`, the outcome will be `0`.
This detecting NULL implementation is more efficent than compares one byte at the time like this:
```c
unsigned int strlen(const char *s) {
char *p = s;
while (*p != ’\0’) p++;
return (p - s);
}
```
> source: [你所不知道的 C 語言:數值系統](https://hackmd.io/@sysprog/c-numerics#%E7%AE%97%E8%A1%93%E5%AE%8C%E5%85%A8%E5%8F%AF%E7%94%A8%E6%95%B8%E4%BD%8D%E9%82%8F%E8%BC%AF%E5%AF%A6%E4%BD%9C