zoukankan      html  css  js  c++  java
  • 编译器思维之结合律

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

    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、细节的东西一定要牢牢的掌握好,这样再复杂的东西都很简单。

  • 相关阅读:
    202006leetcode刷题记录
    二分查找详解
    并查集
    202005leetcode刷题记录
    基于地震数据的Spark数据处理与分析
    Java日志框架:logback详解
    java 多线程
    Oracle表恢复(truncate)
    关于软件开发,你老板不知道的7件事
    调用oracle 分页存储过程 返回游标数据集
  • 原文地址:https://www.cnblogs.com/litifeng/p/8600624.html
Copyright © 2011-2022 走看看