C中的Unsigned char vs char - 字符串的比较

时间:2015-01-30 23:36:06

标签: c string

我在C中做了一个小小的任务,我试图找到比较两个字符串的最佳方法(当然,字符串未在C中定义,因此为char数组)。

这是我的代码:

int equal(char *s1, char *s2)
{
    int a = 0;
    while(!(a = *(unsigned char *)s1 - *(unsigned char *)s2) && *s2) ++s1,  ++s2;
    return (a == 0) ? 1 : 0;
}

它有效但我不知道为什么我必须将我的char转换为unsigned char。

(当然我在作业中不能使用<string.h>。)

2 个答案:

答案 0 :(得分:4)

怎么样

int equal(const char *s1, const char *s2)
{
    int i;
    for (i=0; s1[i] || s2[i]; i++)
        if (s1[i] != s2[i])
            return 0;
    return 1;   
}

或者如果你更喜欢while循环:

int equal(const char *s1, const char *s2)
{
    while (*s1 || *s2)
        if (*s1++ != *s2++)
            return 0;
    return 1;   
}

要回答您的具体问题,为了比较两个字符串(或实际上两个字符),无需将它们转换为unsigned char。我希望你同意我的方法比你的方法更具可读性。

答案 1 :(得分:3)

  1. 原始代码相当理想。对于简单的相等比较,不需要(unsigned char *)强制转换。以下工作正常。 (但请参见第6点):

    int equal(char *s1, char *s2) {
      int a = 0;
      while(!(a = *s1 - *s2) && *s2) ++s1, ++s2;
      return (a == 0) ? 1 : 0;
    }
    
  2. 在制作更优化的代码时,无需像'\0'那样比较空字符if (*s1 || *s2) ...的两个字符串。当代码检查非零a时,仅检查1个字符串就足够了。

  3. “...当然,因为字符串没有在C中定义”并非如此。 C确实定义了“字符串”,但不是类型:

      

    string 是由第一个空字符”C11§7.1.1

    终止并包含的连续字符序列
  4. 如果代码试图不仅仅是简单地比较相等而是命令,那么使用(unsigned char *)是有意义的。即使在这种情况下,类型也可以是char。但是,通过转换为unsigned char甚至signed char,代码可以跨平台提供一致的结果,即使有些charsigned char而其他人为unsigned char

    // return 0, -1 or +1
    int order(const char *s1, const char *s2) {
      const unsigned char *uc1 = (const unsigned char *) s1;
      const unsigned char *uc2 = (const unsigned char *) s2;
    
      while((*uc1 == *uc2) && *uc1) ++uc1, ++uc2;
        return (*uc1 > *uc2) - (*uc1 < *uc2);
    }
    
  5. 在函数签名中使用const允许代码与const char *一起用作order(buffer, "factorial");。否则使用equal(char *s1, char *s2)调用OP的equal(buffer, "factorial");是未定义的行为。如果例程修改了*s1*s2,则受影响的文本将为真,但事实并非如此。使用const确实可以减少某些警告并允许进行一些优化。图片来源:@abligh


    1. 是需要进行投射的角落情况。如果char的范围与int(某些图形处理器执行此操作)并且charsigned char的范围相同,则*s1 - *s2 可以溢出,这是未定义的行为(UB)。当然,charint范围相同的平台很少见。 IMO,即使在这样的机器上也是令人怀疑的,这个代码的非转换版本会失败,但它在技术上是UB。