为什么strcmp返回int而不是char?

时间:2015-05-27 16:10:01

标签: c++ c

据我所知,charint等变量类型之间的唯一区别是它们占用的内存量。我猜他们在调节他们所拥有的变量代表什么方面没有任何作用。如果这是真的,在here中,我看到了strcmp的以下内容:

  

strcmp函数将字符串s1与s2进行比较,返回a   与第一个之间的差异具有相同符号的值   不同的字符对(解释为unsigned char对象,   然后升级到int)。

我想问为什么结果会提升为int?由于char被比较,因此在所有情况下它们的差异都适合char。那么是不是将结果提升到int只是在结果的末尾附加一堆0?那么,为什么要这样做呢?

4 个答案:

答案 0 :(得分:28)

char可能签署也可能不签署。 strcmp必须返回已签名的类型,如果差异为负,则可以为负数。

更一般地说,int是传递和返回简单数值的首选,因为它被定义为这些值的“自然”大小,并且在某些平台上,处理比较小的类型更有效。 / p>

答案 1 :(得分:11)

当然,尽管其他人提到了溢出的可能性,但只有需要能够返回,例如-1,0或1 - 很容易适合签名的字符。真正的历史原因是,在20世纪70年代的原始版本的C中,函数无法返回一个字符,任何尝试这样做都会导致返回一个int。

在这些早期编译器中,int也是默认类型(很多情况,包括函数返回值,如下面的主要部分所示,允许你将int声明为int而不实际使用int关键字),因此定义任何函数没有特别需要返回一个不同的类型作为返回int。

即使是现在,无论如何,char返回只是将值符号扩展到int返回寄存器(pdp11上的r0,x86上的eax)。将其作为char处理将不会有任何性能优势,而允许它作为实际差异而不是强制它为-1或1确实具有小的性能益处。对于比较运算符而言,axiac的回答也很有必要将其提升回int。这些促销的原因也是历史性的,顺便说一下,编译器不必为char和int的每种可能组合实现单独的运算符,特别是因为许多处理器上的比较指令只能用于int。

证明:如果我在Unix V6上为PDP-11制作测试程序,则会忽略char类型并返回范围之外的整数值:

char foo() {
    return 257;
}

main() {
    printf("%d\n", foo());
    return 0;
}

# cc foo.c
# a.out
257

答案 2 :(得分:3)

AFAIK,标准C库没有一个函数可以获取或返回类型char的值。它具有char*const char*类型的参数和返回类型,但不是普通的char

int isalpha(int c);找一个更令人震惊的例子。

我不知道为什么,但我可以猜到。也许这是由于ABI。在我所知道的任何ABI中,类型char的任何参数或返回值无论如何都会在内部提升为int,因此没有必要这样做。它实际上会使代码 less 有效,因为每次使用该函数时都需要截断。

答案 3 :(得分:3)

int提升它返回strcmp()的值的一个可能原因是在调用代码中备用处理器指令。

通常(总是?)*返回的值与comparison operator一起使用。

让我们看看比较运算符的操作数会发生什么。

  

常用算术转换

     

以下算术运算符的参数经历隐式转换以获取公共实数类型,即执行计算的类型:

     
      
  • 二进制算术/%+-<
  •   
  • 关系型运营商><=>===!=&
  •   
  • 二进制按位算术^|?:
  •   
  • 条件运算符int
  •   
     

...

     

4)否则,两个操作数都是整数。在那种情况下,

     

首先,两个操作数都会进行整数提升   ...

(来源:http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions

  

整体促销

     

整数提升是任意整数类型的值的隐式转换,其等级小于或等于int的等级或类型_Bool,int,signed int,unsigned int的位字段的值,类型为{{1 }或unsigned int

(来源:http://en.cppreference.com/w/c/language/conversion#Integer_promotions

返回strcmp()

从上面的引文中可以看出,char返回的strcmp()值可能会提升为int

为什么C的创作者选择返回int

一个非常简单的原因:因为升级无论如何都会发生,并且因为(至少)需要一条处理器指令来执行升级,所以将该指令添加到strcmp()的代码更方便(即在一个地方),而不是在任何地方调用strcmp()函数。

早在70年代,内存和CPU都是非常宝贵的资源。现在似乎无关紧要的优化(在这里和那里保存了几个字节的内存,可能在代码中的几十个位置)当时具有更重要的意义。

更新

再想一想,我认为this answerthis answer提供的历史原因比我的更准确。