在C中默认签名

时间:2013-09-04 01:25:06

标签: c standards

再一次,我正在上课,在那里我可以回答学生关于C的问题。这里有一个我不知道答案:是否有理由接受signed作为C的默认修饰符?人们会认为unsigned是自然的选择。那么,这真的是一个设计决定吗?

5 个答案:

答案 0 :(得分:15)

标准而言(因为您的问题被标记为此类),signed被标记为默认值,因为它是如何使用之前的C实现标准。

最初的ANSI / ISO标准要求是编纂现有的做法,而不是创造一种新的语言。因此,根据基本原理文档,预标准实施的行为是最重要的因素:

  

最初的X3J11章程明确要求编纂现有的共同惯例,C89委员会在明确无误的任何地方都坚持先例。

     

C89定义的绝大多数语言与Brian Kernighan和Dennis Ritchie在C语言编程语言第一版的附录A中所定义的完全相同,并且在当时几乎所有C语言翻译中都有实现。 (该文件在下文中称为K& R.)

如果您希望了解预标准实现首选signed的原因,您可能需要研究最初开发UNIX和C的PDP-n机器的体系结构。 / p>

History of C页面显示unsigned实际上是语言的相对后来者,出现在70年代中期的某个时候:

  

在1973-1980期间,语言有所增长:类型结构获得了无符号,长整数,联合和枚举类型,并且结构变成了几乎一流的对象(缺少文字符号)。

答案 1 :(得分:5)

它主要是向后兼容性,而C语言来自早期语言,不能轻易支持有符号和无符号整数。

C源自一种名为B的旧语言,它源于一种名为BCPL的旧语言(即CPL的简化版本)。

BCPL主要是无类型语言。变量声明没有指定对象的类型;相反,对给定变量的操作会将其视为给定类型。

BCPL运营商+-*/REM将其操作数视为已签名的整数,并产生整数结果。

如果BCPL支持无符号整数,那么要么必须有另一组运算符无符号操作数,要么它根本不能代表负数。 (请注意,BCPL不支持浮点。)

B的语法与BCPL完全不同(并且更接近于C),但它保留了大部分相同的语义。特别是,变量和函数默认为整数类型 - 并且没有unsigned关键字。

早期C,基于B,也没有unsigned关键字。它只有四种基本数字类型:charintfloatdouble。 (unsigned已添加longunionenum,有些时间介于1973年至1980年之间。)鉴于语言的弱类型,程序员有时会在需要无符号算术时使用指针。

没有声明类型的实体隐式具有类型int的“特征”保留在C中,直到1999 ISO标准最终删除了“隐式int”规则。

此外,有符号整数类型往往比无符号类型更有用。表示负值的能力非常方便。给定典型的环绕语义,两个小值的无符号减法中的错误可以产生巨大的正值(例如,3 - 4 == 65535,对于16位无符号类型)。即使在作为所有这些语言的主要目标的系统编程领域中,有时也需要表示负值(例如,某些数量的变化)。

参考文献:

答案 2 :(得分:3)

根据The Development of the C Language,无符号的概念是在1973年到1980年之间添加特征时对语言的扩展。虽然没有明确说明,但叙述表明它直到1977年才被引入(见便携性,第3段)。

因此,默认签名是因为该语言最初只有签名类型。

答案 3 :(得分:0)

语言未定义char的默认签名。它由实现定义。有些CPU更自然地签名为char,而其他CPU则更自然地未签名。

答案 4 :(得分:0)

保证

unsigned语义更简单:modulo base-2 n ,没有例外。但是不要假设 n 是什么:范围的大小不需要等于相应签名类型的大小。

唯一的要求是所有正符号值也可以用相应的无符号类型表示。

unsigned的一个有效实现是使用二进制补码有符号算术,并在每次操作后将符号位置零。这不太可能出现在现实生活中,但是使用非二进制补码算法的机器在尝试绕过负数逻辑时会遇到更多麻烦。

在实践中,负数是任何硬件平台的基本特征,但将整个寄存器视为正数的能力只是锦上添花。 C旨在最紧密地围绕硬件的最有效部分。