为了稍微扩展 Michael Madsen 的回答,一个示例可能是 ++ 运算符的行为。非正式地,我们使用简单的英语描述运算符。例如:
如果x 是int 类型的变量,++x 会使 x 加一。
(我假设没有整数溢出,并且 ++x 不返回任何内容)
在形式语义(我将使用操作语义)中,我们还有一些工作要做。首先,我们需要定义类型的概念。在这种情况下,我将假设所有变量都是int 类型。在这种简单的语言中,程序的当前状态可以用存储来描述,存储是从变量到值的映射。例如,在程序的某个时刻,x 可能等于 42,而y 等于 -5351。商店可以用作函数——例如,如果商店s 的变量x 的值为42,那么s(x) = 42。
程序的当前状态还包括我们必须执行的程序的剩余语句。我们可以将其捆绑为<C, s>,其中C 是剩余的程序,s 是商店。
所以,如果我们有状态<++x, {x -> 42, y -> -5351}>,这是一个非正式的状态,其中唯一剩余要执行的命令是++x,变量x 的值为42,变量y 的值为@987654338 @。
然后我们可以定义从程序的一种状态到另一种状态的转换——我们描述当我们在程序中执行下一步时会发生什么。所以,对于++,我们可以定义如下语义:
<++x, s> --> <skip, s{x -> (s(x) + 1)>
有点通俗点,通过执行++x,下一个命令是skip,没有任何作用,并且store中的变量没有变化,除了x,它现在有原来的值加上一。还有一些工作要做,例如定义我用于更新商店的符号(我没有这样做来阻止这个答案变得更长!)。因此,一般规则的一个具体实例可能是:
<++x, {x -> 42, y -> -5351}> --> <skip, {x -> 43, y -> -5351}>
希望这能给你这个想法。请注意,这只是形式语义的一个示例——除了操作语义,还有公理语义(通常使用 Hoare 逻辑)和指称语义,可能还有很多我不熟悉的。
正如我在对另一个答案的评论中提到的,形式语义的一个优点是您可以使用它们来证明程序的某些属性,例如它终止。除了显示您的程序没有表现出不良行为(例如不终止)外,您还可以通过证明您的程序符合给定规范来证明您的程序按要求运行。话虽如此,我从来没有发现指定和验证程序的想法令人信服,因为我发现规范通常只是用逻辑重写的程序,因此规范很可能是错误的。