一般的C语言程序设计文本对C运算符的分类大概都是分为五大类:算术运算符、 关系运算符、逻辑运算符、按位运算符和一些特殊任务的运算符。这种分类法表面上“合情合理”,事实相当的笼统含混。算术运算符好理解,什么叫关系运算符,关系可运算么?关系是什么数据值参与运算?
不甘于这种含混的分类法,这几天花了一点时间对C语言的全部运算符进行分拣,分别从设计、语义和哲学等多个角度对C运算符进行分析,并且归纳出以下五类:
- 计算指令
- 判断指令
- 保存指令
- 对象元操作指令
- 自定义指令
此分类的根据是机器的功能,理解它需一些计算理论知识,分类标准在尾部解析。
运算符与机器指令
从语言与机器的关系看,运算符就是操值指令,C语言操作符就是C语言机的指令。本文将[运算符]替换为更本质的[指令]一词,理解时可互换。
- 注意:每种运算符的操作数都有约定的值类型,详细请看标准
- 注意:运算符有优先级和结合性两项本质属性
计算指令
‘计算’一词其实不够深刻,计算的概念源自具体的特殊的算术运算,可以的话用[操值指令]更一般更深刻。
二元算术指令
- 设计:数值计算,二元操值指令,对二值进行物理增减,操值结果类型不变(逻辑:概念的处理)
- 语义:在信息值A的基础上添加或整倍添加、去除或整倍去除信息值
- 哲学:机器是“懂”信息单位——整数和浮点数,并且会这种数值物理增去操作
- 指令:
Addition and subtraction. Defined on integral types,
floating-point types and pointer types.
`*, /, %’
Multiplication, division, and modulus. Multiplication and
division are defined on integral and floating-point types.
Modulus is defined on integral types.
一元算术指令
- 哲学:在算术指令的语义基础上复合了少许操作语义,让语言表达更紧凑
- 指令:
Increment and decrement. When appearing before a variable, the
operation is performed before the variable is used in an
expression; when appearing after it, the variable’s value is used
before the operation takes place.
`-,+’
Negative. Defined on integral and floating-point types. Same
precedence as `++’.
按位指令
- 设计:位级计算(操值)
- 语义:计算机处理二进制数据,对二整数[按位]进行复合判断,产生新值
- 哲学:按位指令复合了复合判断、取一位和移位等操作语义(后两个与具体机器相关),这是对指令复杂化的典型例子。
- 指令:
Bitwise OR. Defined on integral types.
`^’ 按位异或
Bitwise exclusive-OR. Defined on integral types.
`&’ 按位与
Bitwise AND. Defined on integral types.
`~’ 按位非
Bitwise complement operator. Defined on integral types. Same
precedence as `++’.
`<<, >>’ 移位
left shift, and right shift. Defined on integral types.
判断指令
为机器提供go where的根据
关系判断指令
- 设计:逻辑推理,用于流程控制,决于机器“go where”去向的根据,二元操值指令,对二值的[数值关系](大小相等)进行判别,产生一个真值(逻辑:判断)
- 语义:比对数值信息A与B,对“数值关系判断P:A OP B”进行真假估值
- 哲学:机器懂数值大小,并且懂真值
- 指令:
Equality and inequality. Defined on scalar types. The value of
these expressions is 0 for false and non-zero for true.
`<, >, <=, >=’
Less than, greater than, less than or equal, greater than or equal.
Defined on scalar types. The value of these expressions is 0 for
false and non-zero for true.
复合判断指令(常称逻辑指令)
- 设计:逻辑推理(同上),二元或一元操值指令,对(二)真值(0为假非0为真)的进行复合判断,产生一个真值(逻辑:复合判断——合取、析取和反取)
- 语义:比对真值信息(只有真假二值)A与B,进行逻辑的信息计算,产生一个真值,这种计算不像数值计算那是物理的,它是逻辑的,按一种[抽象的规则]进行输入输出计算,例如“逻辑与”,它的规则就是当A和B都为真时,计算结果为真,否则结果为假。虽然这些规则是逻辑的,但它不是人造的,而是客观规律决定的。真值与数值是客观世界最抽象信息量最小的信息单位;并且它们是完全不同类型的信息,相应有不同类型的操值方法,真值无加减之说,数值亦无或非之言;真值对“思维如实反映客观世界与否”进行抽象;数值对“数量信息”进行抽象。用哲学的术语理解,真值是思维与存在关系的描述,数值只是对存在进行客观描述。当大脑进行单一的推理(归纳演绎等)时,不涉及真值的评判,但当论证,尤其是复合论证决策带有未知的判断时,真值必须介入。
- 哲学:机器懂与、或、非的逻辑语义
- 指令:
Logical OR. Defined on integral types.
`&&’
Logical AND. Defined on integral types.
`!’
Logical negation. Defined on integral types. Same precedence as
`++’.
条件指令
- 设计:对二路分支精简化,特殊化
- 语义:
- 哲学:复合判断指令和估值操作,不是简单的估值
- 指令:
The ternary operator. `A ? B : C’ can be thought of as: if A
then B else C. A should be of an integral type.
保存指令
实现机器的保值功能
赋值指令
- 设计:操值(计算)结果(状态)保存,简单搬动数据
- 语义:把右值(表达式)估到的值保存到左值指向存储区
- 哲学:赋值指令不同于算术等计算指令,亦不似于逻辑判断指令取得go where根据,它属于机器第三种最基本的指令,与机器的记忆体部分相关联。
- 指令:
Assignment. The value of an assignment expression is the value
assigned. Defined on scalar types.
`OP=’
Used in an expression of the form `A OP= B’, and translated to
`A = A OP B’. `OP=’ and `=’ have the same precedence. OP is any
one of the operators `|’, `^’, `&’, `<<’, `>>’, `+’, `-’, `*’,
`/’, `%’.
对象元操作指令
对象地址指令
- 设计:取得对象地址值,或直接对地址指向区进行取值(没有估求过程)
- 哲学:对象地址不属于C语言计算的概念,属于物理机器的一个概念,只是利用了机器实现的一个技巧。虽然C中有地址运算,那只是过顺水推舟,利用这种技巧实现了某高级语义,比如数组访问。
- 指令:
Pointer dereferencing. Defined on pointer types. Same precedence
as `++’.
`&’
Address operator. Defined on variables. Same precedence as `++’.
对象类型指令
- 设计:
- 哲学:
- 指令:
求某特殊对象大小,单位字节
‘sizeof ( typename )’
求对象类大小
‘(typename) expr’
强制类型转换
对象内部访问指令
Structure member, and pointer-to-structure member. For
convenience, GDB regards the two as equivalent, choosing whether
to dereference a pointer based on the stored type information.
Defined on `struct’ and `union’ data.
`.*, ->*’
Dereferences of pointers to members.
`[]‘
Array indexing. `A[I]‘ is defined as `*(A+I)’. Same precedence
as `->’.
自定义指令
- 设计:函数 type f(a,b,…),a,b, … can be any type.
- 哲学:函数的真正身份是机器指令,一种复合的高级指令。在上面提到的C基本指令和相对应的数据类型的基础上复合出更多更复杂的完成某种计算任务的指令。
- 指令:
Function parameter list. Same precedence as `->’.
到此,C运算符的真面目被函数原型表露无遗:
type f(a,b,c,…)
操作数、操作名和操作结果类型。
估值、操值、保值和go where
计算理论中对图灵机功能的描述是这样的,读、根据内部状态和硬编码规则产生移动和写。由于图灵机是抽象的,它的功能部件与实际的机器上并没有一对一的实现。有学过通信理论的同学可以用通信模型来理解实际机器如何现实图灵机计算。
通信是一种交流活动,交流的主方A将信息翻译成信号(声音或文字),受方B再将信号解释成信息理解。将这个模型套入编程计算的场景时,主方A好比程序员,信号是程序,受方B是机器。机器必须有听取信号和理解信息的功能,对应图灵的读功能,这里把这种功能定义为估值;
另外,要实现计算,机器必须有对信息进行处理的功能,对应图灵机的移动(或复加写)功能,这里把这种功能一般化为操值;
如果计算只有单独一步,那么机器只需要具备估值和操值的功能足矣,但是程序是多步计算,所以机器还必须具有go where的功能(默认是go next)和保存中间计算结果的功能。前者叫go where,后者叫保值。
