# 2019q1 Homework3 (review) contributed by < `F74021200` > [第三週測驗題(上)-測驗一](https://hackmd.io/s/S1weT4iLE#) cst_memcmp ```click= int cst_memcmp(const void *m1, const void *m2, size_t n) { const uint8_t *pm1 = (const uint8_t *) m1 + n; const uint8_t *pm2 = (const uint8_t *) m2 + n; int res = 0; if (n) { do { int diff = *--pm1 - *--pm2; res = (res & (((diff - 1) & ~diff) >> 8)) | diff; } while (pm1 != m1); } return ((res - 1) >> 8) + (res >> 8) + 1; } ``` 由 [c99 standard-page 85](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf) : The result of E1 >> E2 is E1 right-shifted E2 bit positions.If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of $E1/2^{E2}$.If E1 has a signed type and a negative value, the resulting value is implementation-defined. 因此,非負整數作 right shift n bits 時,是採用除法定義;但對於負整數之 right shift 則是 implementation-defined ,所以,對於負整數之 right shift 是 [logical right shift](https://en.wikipedia.org/wiki/Logical_shift) 還是 [arithmetic right shift](https://en.wikipedia.org/wiki/Arithmetic_shift) 或是[其他種 right shift](https://en.wikipedia.org/wiki/Circular_shift) ,取決於編譯器的實作,[由 gcc 之說明](https://gcc.gnu.org/onlinedocs/cpp/Implementation-defined-behavior.html#Implementation-defined-behavior) 知: ...implementation-defined. This term means that the implementation is free to do what it likes, but must document its choice and stick to it. 並[由此](https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation) 知: Signed ‘>>’ acts on negative numbers by sign extension. 此適用於 C90 6.3, C99 與 C11 6.5 ,因此,在使用 c99 標準時,有號負數在作 right shift 時,需要 sign extension diff 之值域: $diff\in\\ \{\ 11111111\ 11111111\ 11111111\ 11111111\ \}\ \cup\ \\\{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111110 \geq x \geq 11111111\ 11111111\ 11111111\ 00000001\ \}\ \cup\ \\\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}\ \cup\\ \\\{\ 00000000\ 00000000\ 00000000\ 00000001\ \}\cup\\\{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000010 \leq x \leq 00000000\ 00000000\ 00000000\ 11111111\ \}$ 對應以上之 diff 之值, diff - 1 之值域: $diff - 1 \in\\ \\\{\ 11111111\ 11111111\ 11111111\ 11111110\ \}\ \cup\\\{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111101 \leq x \leq 11111111\ 11111111\ 11111111\ 00000000\ \}\ \cup\ \\\{\ 11111111\ 11111111\ 11111111\ 11111111\ \}\ \cup\\ \{\ 00000000\ 00000000\ 00000000\ 00000000\ \}\ \cup\\\{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000001 \leq x \leq 00000000\ 00000000\ 00000000\ 11111110\ \}$ ~diff 之值域: $\sim diff\in\\ \{\ 00000000\ 00000000\ 00000000\ 00000000\ \}\ \cup\ \\\{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000001 \leq x \leq 00000000\ 00000000\ 00000000\ 11111110\ \}\ \cup\ \\\{\ 11111111\ 11111111\ 11111111\ 11111111\ \}\ \cup\\ \\\{\ 11111111\ 11111111\ 11111111\ 11111110\ \}\cup\\\{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111101 \leq x \leq 11111111\ 11111111\ 11111111\ 00000000\ \}$ ### ((diff - 1) & ~diff) >> 8 #### case1. If $diff \in \{\ 11111111\ 11111111\ 11111111\ 11111111\ \}$ then $diff - 1 \in\{\ 11111111\ 11111111\ 11111111\ 11111110\ \}$ $\sim diff \in\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ $((diff - 1)\ \&\ \sim\ diff)\ >>\ 8 \in\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ #### case2. If $diff\\\in \{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111110 \geq x \geq 11111111\ 11111111\ 11111111\ 00000001\ \}$ then $diff - 1 \in\\\{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111101 \leq x \leq 11111111\ 11111111\ 11111111\ 00000000\ \}$ $\sim diff \in\ \\\{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000001 \leq x \leq 00000000\ 00000000\ 00000000\ 11111110\ \}$ $((diff - 1)\ \&\ \sim diff)\ >>\ 8 \in\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ #### case3. If $diff\in \{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ then $diff - 1 \in\{\ 11111111\ 11111111\ 11111111\ 11111111\ \}$ $\sim diff \in\{\ 11111111\ 11111111\ 11111111\ 11111111\ \}$ $((diff - 1)\ \&\ \sim\ diff)\ >>\ 8 \in\{\ 11111111\ 11111111\ 11111111\ 11111111\ \}$ #### case4. If $diff\in \{\ 00000000\ 00000000\ 00000000\ 00000001\ \}$ then $diff - 1 \in\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ $\sim diff \in\{\ 11111111\ 11111111\ 11111111\ 11111110\ \}$ $((diff - 1)\ \&\ \sim\ diff)\ >>\ 8 \in\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ #### case5. If $diff\\\in\{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000010 \leq x \leq 00000000\ 00000000\ 00000000\ 11111111\ \}$ then $diff - 1 \in\\\{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000001 \leq x \leq 00000000\ 00000000\ 00000000\ 11111110\ \}$ $\sim diff \in\ \\\{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111101 \leq x \leq 11111111\ 11111111\ 11111111\ 00000000\ \}$ $((diff - 1)\ \&\ \sim diff)\ >>\ 8 \in\{\ 00000000\ 00000000\ 00000000\ 00000000\ \}$ ### 由以上五點知: $Let\ f(diff) = ((diff - 1) \& \sim diff)\ >>\ 8,\\ A = \{\ x\ |\ 11111111\ 11111111\ 11111111\ 11111111 \geq x \geq 11111111\ 11111111\ 11111111\ 00000001\ \},\\ B = \{\ x\ |\ 00000000\ 00000000\ 00000000\ 00000001 \leq x \leq 00000000\ 00000000\ 00000000\ 11111111\ \},\\and\ diff\ \in\ A\cup B\cup\{00000000\ 00000000\ 00000000\ 00000000\} \\then\\f(diff) =\begin{cases}\ 11111111\ 11111111\ 11111111\ 11111111\ , & \text{if diff = 00000000 00000000 00000000 00000000} \\ \ 00000000\ 00000000\ 00000000\ 00000000\ , & \text{otherwise}\end{cases}$ ### res = (res & f(diff)) | diff $Let\ g(res,\ diff) = (res\ \&\ f(diff))\ |\ diff\\then\\g(res,\ diff)=\begin{cases}res, & \text{if diff = 00000000 00000000 00000000 00000000} \\diff, & \text{otherwise}\end{cases}$ 當 $diff = 00000000\ 00000000\ 00000000\ 00000000$ 時, res 會等於進這次 loop 前的 res ,當 $diff\ \in A\cup B$ , res 會等於這次 loop 的 diff 。 ### 所以,每次遞迴,當比對的 byte 數值相同時, res 會等於進這次 loop 前的 res 值,當比對的 byte 不相同時, res 會等於這次 loop 的差值。也就是說,若比對的 n byte 中,每個 byte 都相同時, res 會等於 res 的初始值, 0 ;若比對的 n byte 中,出現不同的 byte 時, res 之值會等於最後一次兩 byte 比對發生不同時的兩 byte 之差值。 ### 另外,由以上等式可知, res 的值域與 diff 相同。 ### 最後討論回傳值: ### ((res - 1) >> 8) + (res >> 8) + 1 #### case1. If $res\ =\ 00000000\ 00000000\ 00000000\ 00000000,\\then\\res\ -\ 1\ =\ 11111111\ 11111111\ 11111111\ 11111111\\(res\ -\ 1)\ >>\ 8\ =\ 11111111\ 11111111\ 11111111\ 11111111\\res\ >>\ 8\ =\ 00000000\ 00000000\ 00000000\ 00000000\\((res\ -\ 1)\ >>\ 8)\ +\ (res\ >>\ 8)\ +\ 1\\=\ -1\ +\ 0\ +\ 1\ =\ 0$ #### case2. If $res\ \in\ A,\\then\\res\ -\ 1\ \in\ (A\cup\{\ 11111111\ 11111111\ 11111111\ 00000000\})\setminus \{11111111\ 11111111\ 11111111\ 11111111\}\\(res\ -\ 1)\ >>\ 8\ =\ 11111111\ 11111111\ 11111111\ 11111111\\res\ >>\ 8\ =\ 11111111\ 11111111\ 11111111\ 11111111\\((res\ -\ 1)\ >>\ 8)\ +\ (res\ >>\ 8)\ +\ 1\\=\ -1\ +\ (-1)\ +\ 1\ =\ -1$ #### case3. If $res\ \in\ B,\\then\\res\ -\ 1\ \in\ (B\cup\{\ 00000000\ 00000000\ 00000000\ 00000000\})\setminus \{00000000\ 00000000\ 00000000\ 11111111\}\\(res\ -\ 1)\ >>\ 8\ =\ 00000000\ 00000000\ 00000000\ 00000000\\res\ >>\ 8\ =\ 00000000\ 00000000\ 00000000\ 00000000\\((res\ -\ 1)\ >>\ 8)\ +\ (res\ >>\ 8)\ +\ 1\\=\ 0\ +\ 0\ +\ 1\ =\ 1$