使用unsigned char和char

4

我查看了许多strCmp()的实现,发现大多数指针实现都是使用unsigned char。

我的问题是,为什么即使我们不使用"unsigned",返回结果也是一样的(根据我所做的测试)?

如果我不使用它,对于某些值,我会得到错误的结果吗?

最后,char默认是有符号还是无符号的?

示例1

int strCmp(const char* s1, const char* s2)
{
    while(*s1 && (*s1 == *s2))
    {
        s1++;
        s2++;
    }    
    return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}

示例2

int strCmp(const char *S1, const char *S2)
{

  for(; *S1 == *S2; ++S1, ++S2)
    if(*S1 == 0)
      return 0;
  return *(unsigned char *)S1 < *(unsigned char *)S2 ? -1 : 1;
  }

1
字符型变量是有符号还是无符号并没有标准化,而是由实现决定。在旧编译器中通常默认为无符号,但现代编译器通常有更改选项。这对于strcmp()的返回值来说是不够的,你会看到库实现者选择了一个可预测的值。 - Hans Passant
2个回答

9
我的问题是,即使我们不使用"unsigned",我们也会得到相同的结果(基于我所做的测试),为什么在返回中使用它?
由于算术运算是使用类型int完成的,因此如果char带有符号,则由于扩展了它们的符号,您将得到负字符的错误值。
例如:假设您的字符宽度为8位,带有2的补码符号。然后,代码点128处的字符将具有整数值-128,因此与范围[0,127]中的任何字符比较都会比其小,这不是您想要的。首先转换为unsigned char可确保整数值为128。
最后,char默认是无符号还是有符号的?
实际上,这是依赖于实现的定义。因此,请明确使用unsigned char以确保。

1
我查看了许多strCmp()的实现,并发现大多数指针实现都是使用unsigned char。实现标准C库函数int strcmp(const char *s1, const char *s2);的代码被指定为像由unsigned char字符组成的字符串一样执行比较。如果char被实现为signed char或unsigned char,则适用此规则。
对于本子条款中的所有函数,每个字符应被解释为具有unsigned char类型。C11 §7.24.1 3
// Example that performs the correct compare without a possibility of overflow.
int strCmp(const char* s1, const char* s2) {
  const unsigned char *u1 = (const unsigned char *) s1;
  const unsigned char *u2 = (const unsigned char *) s2;
  while((*u1 == *u2) && *u1) {
    u1++;
    u2++;
  }    
  return (*u1 > *u2) - (*u1 < *u2);
}

以下代码在某些机器上会失败,其中unsigned char的范围等于unsigned的范围。

return *(const unsigned char*)s1 - *(const unsigned char*)s2;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接