编译器思维之结合律

Posted 立体风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器思维之结合律相关的知识,希望对你有一定的参考价值。

结合律指的就是操作符优先级的结合方向的规律,共两种“左到右”,“右到左”,好像很简单的样子,但是,你真的全部了解了吗?你了解的是编译器真正的工作方法吗?

1、左到右的含义:就是左结合,右到左就是:右结合。

2、所谓结合:就是多个东西结合成一个整体,变为一个新的东西。

3、当一个操作符是左结合且为双目运算符时,它会把它左边的东西整个当作一个整体并与之结合,右边的只认离它最近的一个,右结合与之相反。

4、举一个算式:a+b+c,这个算式都是加号,大家优先级相同,所以转而考虑结合律,+号是左结合,所以第一个+号,先结合a,并且只认识右边和它最近的b,而对于第二个+号,会把a+b当作一个整体,并与之结合,然后只认识右边和它最近的c。结果就是 ((a)+b)+c

5、来一个复杂的例子:

(*((void (*)())0))()

我第一次看到它时,第一反应是,这是一个正确的表达式吗?呵呵。

1)确定主语,在这里是0,其他的都是修饰它的。

2)离0最近的是一对括号,里面的内容是:void (*)(),其实是一个类型,是我们自定义的一个函数指针类型,用小括号括起来,这个小括号是强制转换符。

3) (void (*)())0 的含义是:把0强制转换为一个函数指针类型。

4) ((void (*)())0) 表示这是一个整体,如果我们把 (void (*)())0 看作一个整体,用一个记号p替换它。

5)这样整个表达式变为: (*p)() ,这句话其实就是利用一个函数指针来调用这个函数,而指针的值p其实是0。

6)综上所述,表达式的作用:让程序指针pc(program counter)跳到地址0。

7)不过我们知道,内存中0地址是被操作系统保护的,所以,这个表达式编译没有任何问题,但执行时候会报“段错误”,因为非法引用被保护的地址。

6、回过头来,继续说优先级:上述表达式简化一下: *(类型)0 ,我们知道强转()和*号均为2级优先符,那么还是结合律在起作用了,它们的结合律是右结合,也就是说(类型)会先和右侧所有内容也就是0结合,然后结合左边的*,而*号会把右侧的所有内容(类型)0看作一个整体,然后进行取值运算,这样好像计算没有啥变化,所以这样是不必要的: *((类型)0

7、再来一个简单的: **p ,作为一个2级指针,因为都是*号,所以优先级相同,结合律为右结合,那么靠近p的那个*号,首先结合p,在结合最左边的*,这时它会将*p看作一个整体进行取值运算,所以不必这样写了: *(*p)

8、细节的东西一定要牢牢的掌握好,这样再复杂的东西都很简单。

以上是关于编译器思维之结合律的主要内容,如果未能解决你的问题,请参考以下文章

关于矩阵乘法结合律的证明

关于矩阵乘法结合律的证明

第十一课:结合律

群,环,域

矩阵结合律的证明-2019.11.29

数字信号处理线性时不变系统 LTI “ 输入 “ 与 “ 输出 “ 之间的关系 ( 周期性分析 | 卷积运算规律 | 交换律 | 结合律 | 分配率 | 冲击不变性 )