算术

算术

stdbool.h 通常定义为:

#define false   0
#define true    1

(来源:开放BSD,穆斯勒, ETC。)

而 unix 程序false- 只有一个不成功的状态代码,定义为:

int
main(int argc, char *argv[])
{
    return (1);
}

为了完整起见,unix程序的定义true是:

int
main(int argc, char *argv[])
{
    return (0);
}

很明显,这与价值完全相反false很明显,它与 stdbool.h 中。我用过的版本来自开放BSD因为 coreutils 的版本更多冗长的

造成这些不同的历史原因是什么?

答案1

程序失败的原因有多种。例如,grep如果找不到所需的模式,或者无法打开指定的文件之一,则会失败。

目前,Unix 允许 1 个(无符号)字节值(返回码)从子进程传回其父进程(我忽略了有关哪个信号杀死了子进程、是否生成了核心等信息,这可能会得到更多信息)位回来)。

由于失败的方式有多种,因此有多个返回代码来编码这些不同的失败,并有一个返回代码来指示成功是有意义的。

由此可见,( 0) 是表示成功的合理选择,其余 (1-255) 表示失败(以及失败的类型)。

完全有可能使用 17 表示成功,并使用 0 到 16 和 18 到 255 表示失败,但为了简单起见,选择 0 表示成功,选择 1 到 255 表示失败,因此有一个范围。同样简单的是使用 255 表示成功,使用 0 到 254 表示失败。然而,这将限制未来的更改以回传超过 8 位,并保持单个故障代码范围的简单性。

答案2

您正在将苹果与梨进行比较。它们的味道不同。 :-)

算术

一个算术 0在 c 和 shell 中都表示 false [a] :

$ if ((0)); then echo true; else echo false; fi
false

或者,在更便携的测试中,但更复杂:

$ echo $(( 22 == 23 ))
0

[a] 实际上,正在写入的是一个 ASCII 字符 ( 0)(在大多数系统中为 ASCII,但也可能是其他系统),其十进制字节值48被透明地转换为0(A c charof value 0) 的字节值。这个字节值是否0意味着 false在c中

对于大多数 shell 来说都是如此,因为算术扩展实际上是 c 算术的直接副本。那里不应该存在任何差异。

退出状态

但实用程序的退出状态 ( $?) 有所不同:

$ echo "$(( 22 == 23 )) $? -- $((22 == 22 )) $?"
0 0 -- 1 0

理论

对于造成这种情况的原因,我只能提出自己的看法。

经典逻辑,以其预期的语义,真值为真(用 1 或维鲁姆 ),以及不真实或错误(用 0 或福尔苏姆

命题逻辑真值表:我们将 true 值表示为 1,将 false 值表示为 0。

nothing/empty那只是人类更接近的思维方式的编纂false

该描述得到用c语言编码

但是对于错误的退出状态只有一个值 ( 0) 似乎太狭窄了,逻辑颠倒过来, ( 0) 改为成功,为几种可能的错误原因留下更多代码。这就是它在 shell 中的使用方式。

答案3

true = 1 和 false = 0 的由来

如果您想知道为什么 true 为 1 而 false 为 0 的历史背景,那么我想指出布尔代数是由 George Bool 在 1847 年“发明”的。这远远早于第一台电子计算机。布尔代数发表于《逻辑的数学分析》。您可以阅读古腾堡项目的副本:http://www.gutenberg.org/files/36884/36884-pdf.pdf

我并没有声称已经详细阅读过它,但我已经浏览了足够多的内容,发现乔治·布尔本人使用 1 作为 true,使用 0 作为 false。


布尔对计算的影响

布尔的代数(“布尔代数”)在很大程度上被忽视,直到他死后很久才被人们拾起并用于计算。甚至在基于硅的计算机之前,布尔代数就在二进制电子学方面变得有用(而不是模拟)。将数学逻辑运算符转变成晶体管接线很简单(请参阅这里)。从那里开始,将多个逻辑门连接在一起以表示二进制数和进行简单的算术运算


关于“if”语句,这些语句源自 CPU 的“条件跳转”操作,其中跳转goto在高级语言中称为跳转。

对于条件跳转,CPU 必须定义一种有用的方法来选择跳转或不跳转。两个最常见的条件是“如果为零则跳转”和“如果为负则跳转”(参见第 39 页带下划线的这里)。然而,将数字解释为正数或负数可能是主观的,因为相同的 CPU 操作用于两人的赞美有符号整数作为“无符号”整数。

所以这就是说,常见的if说法将 0 表示为假,1 表示为真,因为:

  • 负/正定义不适用于无符号整数
  • 0 代表真,1 代表假,这与常用的布尔代数相反

为什么外壳不一样?

外壳做相反事情的起源很难找到。 0 的成功肯定可以追溯到 20 世纪 70 年代可能是unix的最早版本没有把握)。

我自己的看法是,一个项目只能以一种方式完全成功,但在很多方面都会失败。

看起来很清楚的是trueandfalse命令的设计是为了符合 shell 对在条件逻辑中使用命令的退出状态的解释:

if first_command ; then
    second_command
fi

如果上面的代码的意思是second_command如果first_command成功就运行。那么对于总是成功的逻辑占位符来说,一个好名字就是true

答案4

我只能想到这个理由,而且对我来说似乎相当有力。

将布尔运算转换为计算机算术的最简单方法是使用0forFALSE1for TRUE,然后使用它们进行的所有运算都有意义,即

TRUE  && TRUE =  TRUE  ( 1 * 1 = 1)
TRUE  && FALSE = FALSE ( 1 * 0 = 0)
TRUE  || FALSE = TRUE  ( 1 + 0 = 1)
FALSE || FALSE = FALSE ( 0 + 0 = 0)

等等等等。

同时程序需要多种退出状态来报告各种错误。将正确的退出状态设置为0,然后使用剩余的 255 (无符号字符)作为错误的退出状态是合乎逻辑的。

当然,现在本来1可以取得良好的退出状态,但随后糟糕的退出状态就会变成一堆撕裂的阵列02..555这是非常不合逻辑的。

相关内容