zoukankan      html  css  js  c++  java
  • 关于左值 右值的一些研究

       中国人的优良传统总是喜欢考一些看起来稀奇古怪但是实际上有没有什么用的一些题目,从而来显示自己出题水平的高超,深以难倒广大考生为乐,就比如这一道坑爹的题目:贴上代码:

      

    int i=3;
    int a=(i++)+(i++);
    a=?
    

     看到这种题目我就瞬间抓狂了,说句实话我是真心佩服那帮中国所有的出题人,怎么恶心人怎么出,真心我去年买了个表。

      对于这种未定义行为的c语言我是不赞成的,本身的定义都模糊的东西怎么可以拿出来用呢,这不是明显逻辑上的犯抽吗?尽管对这种题目很蛋疼,但是做为一个万年中国应试教育下的孩子,我还是对这种题目打算好好研究下,当然,如果我要是这么研究下去就和我题目的主题不符了,我这里拐了个弯,我先研究了下关于运算符优先级的问题,尽管这个表达式的优先级看起来是那么的一目了然。

      我先随机抽取了几个单目运算符的表达式,贴代码:gcc 编译

    int a=9;
    int *p=&++a;
    int tmp=*&a;
    int tmp_1=!--++a;
    int tmp_2=--++a;
    int tmp_4=--a++;
    int tmp_3=!++a;
    

     结果报错,有几条错误如下,错误结果如下:lvalue required as unary ‘&’ operand;lvalue required as decrement operand ,翻译过来就是在自加运算和&一元操作中必须要为左值,很好我们现在终于来到了我们的主题,对于左值和右值的区别,我们老师以前模糊的和我们有过简单的交流,左值就是赋值操作符左边的数,是可以进行修改的,右值是赋值操作符右边的数,是不可以修改的,同样的左值也不一样在赋值操作符的左边,也可以在右边,

      比如    int i=2;

         int j=i;

    很明显这么简单的解释根本无法解释上述的错误,左值和右值依旧是拦路虎。

    经过网上的资料参考,消化吸收后,真心感谢网上的开源精神,看到这么一句话——赋值操作符、自增/自减操作符 (++/–)、取地址操作符 (&,注意该操作符同时要求操作数不能是bit field,以及不能使用register进行修饰) 等要求其操作数必须是左值。对应我上述代码,颇有隔靴搔痒之嫌。几番研究,恍然大悟。贴code

        int i=0;
        (++i)=5;
        (i++)=5;
    

      编译错误已出;lvalue required as left operand of assignment 赋值左边的操作数要求是左值,我们首先确定了i是一个左值,进行自增自减当然是可以的不会报错,但是自增表达式的值不是一个左值,那么赋值操作符当然无法通过,要求左边必须是左值,当然这种情况在c++中因为运算符重载的关系已经变过了,我们这里不加以引申,后期如果可以的话我还会加以讨论,我们这里只进行对于C语言的研究。

      我姑且认为自增表达式中我们得到的值应该是i的一份临时拷贝,只不过i++ 与++i 一个是返回i的拷贝然后才进行i的对i这个操作数的加1,一个是加1之后返回这个数的拷贝,都是一份临时的拷贝,我们并不知道这个表达式的值放在内存的什么地方,也无法保证表达式的值一次还会放在他的老地方,所以++是一个返回右值的表达式。

       明白了这个关系,那么我们用一些式子来加深对左值和右值的概念

     

     

      

         char cha='a';
    	char *p=&cha;
    	*p='a';
    	char tmp=*p;
    	char tmp_1=*p+1;
    	char tmp_2=*(p+1);
    	*(p+1)='b';
    	char tmp_3=(*p)+1;
    	char *tmp_4=++p;
    	char *tmp_5=p++;
    	char tmp_6=*++p;
    	*++p='c';
    	char tmp_7=*p++;
    	*p++='d';
    	char tmp_8=++*p;
    //++*p='d';
    	char tmp_9=(*p)++;
    //(*p)++='c';
    	char tmp_10=++*++p;
    //++*++p='c';
    	char **p1=&p;
        char tmp_11=*++*p1;
    	*++*p1='c';
    //char tmp_12=*++++p;
    //*++++p='a';
    

      

    这些式子摘自http://blog.sina.com.cn/s/blog_8af6bbd10100ybid.html 特此声明。明白了这些式子相信对于左右值理解更加深刻。暂时就说这么多,以后关于c++的继续补充。

      

          

  • 相关阅读:
    sync.waitGroup的wait可以多次wait,同时通知
    广播与服务(2)
    Android中的广播与服务(包含代码)
    Android的Activity的页面跳转和数据传递
    Android基础4(get、post乱码解决、Asynchttpclient的GET_POST访问网络、上传文件、多线程下载、多线程下载的Android移植、XUtils实现多线程下载)
    Android3的知识点补充
    Android基础3(数据库创建、增删改查、事务、listView)
    Android基础2(包含测试、保存数据、获取目录等)
    关于Android的基础概念
    c++与c几点比较
  • 原文地址:https://www.cnblogs.com/chongxin/p/3226397.html
Copyright © 2011-2022 走看看