C strcmp实现使用减法字符

mad*_*ski 32 c

我看到了这段时间的实施strcmp,我有一个纯粹教育目的的问题.为什么需要将输入转换为16位整数,进行数学运算然后转换回8位?在8bit中进行减法有什么问题?

int8_t strcmp (const uint8_t* s1, const uint8_t* s2)
{
  while ( *s1 && (*s1 == *s2) )
  {
    s1++; 
    s2++;
  }

  return (int8_t)( (int16_t)*s1 - (int16_t)*s2 );
}
Run Code Online (Sandbox Code Playgroud)

注意:代码假定为16位int类型.

编辑: 有人提到C int默认转换为(假设为32位).即使代码明确声明要转换为16位,情况也是如此int吗?

Rin*_*g Ø 24

STRCMP(A,B)功能有望恢复

  • <0 如果 string a < string b
  • >0 如果 string a > string b
  • 0 如果 string a == string b

测试实际上是在同一位置的两个字符串中的第一个字符不同(0,字符串终止符,也适用).

这里由于函数有两个uint8_t(无符号字符),开发人员可能是担心这样做对两个无符号字符比较会给之间的数字0255,因此绝不会返回一个负值.例如,118 - 236将返回-118,但在8位上它将返回138.

因此程序员决定转换为有int_16符号整数(16位).

这可能有效,并给出正确的负值/正值(假设函数返回int_16而不是int_8).

(*编辑:@zwol下面的评论,整数提升是不可避免的,因此int16_t不需要这个演员)

然而,最终的int_8演员打破了逻辑.由于返回的值可能来自-255to 255,因此其中一些值会在强制转换后看到它们的符号反转int_8.

例如,do 255 - 0给出正255(16位,所有低8位为1,MSB为0)但在int_8世界上(8位的有符号int)这是负的-1,因为我们只有最后的低8位设置为二进制11111111或十进制-1.


绝对不是一个好的编程示例.Apple的

那个功能更好

for ( ; *s1 == *s2; s1++, s2++)
    if (*s1 == '\0')
        return 0;
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
Run Code Online (Sandbox Code Playgroud)

(Linux在汇编代码中执行...)

  • 无论有没有转换为`int16_t`,由于整数提升,实际的减法将在`int`上完成.`int`被允许与`int16_t`的类型相同,但是***允许与`int8_t`的类型相同,因此整数提升是不可避免的; 没有办法(在标准范围内)迫使C实际对`[u] int8_t`数量进行算术运算.(注意`int8_t`和`char`之间的区别;在`CHAR_BIT> = 16`的实现中,`int`和`char`可能是同一类型;但是,这样的实现根本不能提供`int8_t` !) (2认同)

Jan*_*dec 9

实际上,差异必须至少为16位¹,原因很明显,结果的范围是-255到255,而不适合8位.但是,sfstewman是正确的,因为无论如何都会由于隐式整数提升而发生.

最终转换为8位是不正确的,因为它可能会溢出,因为范围仍然不适合8位.无论如何,strcmp确实应该回归平原int.


¹9就足够了,但通常是8个批次.