14

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

4

5 回答 5

15

标准而言(因为您的问题被标记为这样),signed被标记为默认值,因为这就是标准之前的 C 实现的情况。

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

最初的 X3J11 章程明确要求编纂现有的通用实践,并且 C89 委员会坚持先例,只要这是明确和明确的。

C89 定义的绝大多数语言与 Brian Kernighan 和 Dennis Ritchie 在 The C Programming Language 第一版的附录 A 中定义的完全相同,并且在当时几乎所有的 C 翻译器中都实现了这一点。(本文档以下简称 K&R。)

如果您想找出为什么首选标准实现signed,您可能必须研究最初开发 UNIX 和 C 的 PDP-n 机器的体系结构。

C页面的历史显示它unsigned实际上是该语言的相对较晚者,出现在 70 年代中期的某个时候:

在 1973-1980 年间,该语言有所发展:类型结构获得了 unsigned、long、union 和枚举类型,并且结构几乎成为一流的对象(仅缺少文字符号)。

于 2013-09-04T01:28:53.333 回答
5

它主要是关于向后兼容性,以及 C 从早期语言的血统,这些语言不能轻易地支持有符号和无符号整数。

C 派生自一种称为 B 的较旧语言,而 B 又源自一种称为 BCPL 的更古老的语言(它是 CPL 的简化版本)。

BCPL 在很大程度上是一种无类型语言。变量声明没有指定对象的类型;相反,对给定变量的操作会将其视为给定类型。

BCPL 运算符+, -, *, /, 并将REM其操作数视为有符号整数,并产生整数结果。

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

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

早期的 C,基于 B,也没有unsigned关键字。它只有四种基本数字类型:charintfloatdouble。(在 1973 年和 1980 年之间的某个时间,与、和unsigned一起被添加。)鉴于语言的弱类型特性,程序员有时在需要无符号算术时使用指针。longunionenum

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

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

参考:

于 2013-09-04T02:29:07.250 回答
3

根据The Development of the C Language,无符号的概念是在 1973 年至 1980 年间向该语言添加功能时对该语言的扩展。虽然没有明确说明,但叙述表明它直到 1977 年才引入(参见Portability,第 3 段)。

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

于 2013-09-04T01:41:52.747 回答
0

unsigned语义保证更简单:以 2 n为模,没有例外。但是不要假设n是什么:范围的大小不需要等于相应有符号类型的大小。

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

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

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

于 2013-09-04T04:21:59.367 回答
0

的默认签名char不是由语言定义的。它由实现定义。一些 CPU 更自然地是有符号的字符,而另一些 CPU 更自然地是无符号的。

于 2013-09-04T01:28:37.727 回答