内存 变量 指针(三) 表达式与自增后缀运算

 

0. 表达式由运算符及其操作数组成

     i++             ++ 是后自增运算符, i是它的操作数

     i+=1           += 是求和赋值运算符,  i和1都是它的操作数, i是左操作数, 1是右操作数

 

1. 左值和左值表达式

    可以放在赋值运算符左侧的操作数是左值

    如果一个表达式的计算结果是左值,那么这个表达式是左值表达式

    所以左值表达式也可以放在赋值运算符的左侧

2.右值和右值表达式

    右值不能放在赋值运算符左侧

       如果一个表达式的计算结果是右值,那么这个表达式是右值表达式

     例如:

           1                         数值常量, 字面值

          'A'                         字符常量, 字面值

          "ABC"                   字符串常量, 但做为一个表达式, 它的值是这个字串在内存中的首地址
                                       所以它实际是一个只读指针(这个不是右值表达式, 是只读的左值表达式)

          1+2                      数值求和表达式, 结果是右值, 所以是个右值表达式

          int i=1;  i++ ;         i++的结果是右值,所以是个右值表达式

    (未经验证,是当前的猜测:右值不在内存中存放, 是个"瞬间值",只出现在CPU寄存器中,所以没有地址)

    

3.指针变量的声明和它的"间接访问表达式" (按首地址读写内存)

       int a=1;

       int *p_int=&a;              指针变量声明,同时对指针变量赋初值

            *p_int=3;                 对"间接访问表达式"赋值, *p_int是个表达式, 是个左值表达式

 

       第二行和第三行的赋值表达式的形式相似,不易理解

       第二行是对p_int这个变量进行赋值 (初始化, 因为这一行是变量声明)

       第三行是对 *p_int这个表达式赋值 (这里出现了p_int这个变量,但不是对它赋值, 而是对整个表达式赋值)

 

       3.1 在C语言中指针变量的一个重要用法就是通过*运算符形成一个"左值表达式"

             再对整个"左值表达式"的计算结果(左值)进行赋值

       3.2 "左值"就是内存中特定的一片字节,这与第一篇中的观点对应

                  (一个变量就是内存中特定的一段连续的字节,一段可以存入和读出数据的内存字节)

 

        3.3 除了*外, []本质上也是间接访问运算符, 一个数组变量的某个元素, 实质上是个表达式,一个左值表达式

              int a[3]={1,3,5};

              a[1]+=1;                   a[1]是个左值表达式(但a是只读指针变量),对它赋值, 就是对特定内存段写入数值

 

6.关于i++和++i

         i++ 这个表达式的计算结果是 "自增前的i"

                    (注意, i++是个右值表达式, "++"会对i的值加1,但整个表达式的值是i自增前的值)

     ++i 这个表达式的计算结果是 "自增前的i"+1                 (注意, ++i也是个右值表达式)

 

      int a, i=1;
         a=i++;   //a=1
         a=++i;    //a=3

 

         下面这两行说法本身没问题, 但会给我们以严重的误导

      i++是在使用i这个变量之后, 再对i进行自增运算

      ++i是在使用i这个变量之前, 先对i进行自增运算

         a=i++;          按上面说法,似乎是用ia赋值,这是错误的

      在对a赋值时,并不使用i的值, 而是使用 i++这个表达式的值,也就是i++这个表达式的计算结果

 

18-08-06 补充例子: ++作为后缀使用时, 会在所在表达式求值完成后, 再对运算数+=1。注意赋值表达式也是"表达式"

#include <stdio.h>
#include <stdlib.h>

    
int main()
{
	int i=3, j=0;

    j -= (i++ + j++, (i++*3 + i++*2 +j++) * 2);
	printf("i=%d,  j=%d\n", i, j);
	printf("%d, %d\n", (i++*2, i++), i);
	printf("%d\n", i);
    getch();
	return 0;
}

int i=2; i=i++; 
以上两个语句中第二个语句是赋值表达式语句, 其中有两个表达式需要计算求值, 
第一个是i++, 表达式计算结果值为2, 
所以第二个表式就是i=2, 这时i被赋值为2, 整个赋值表达式的值也是2, 至此计算求值完成
这时发生i+=1, 所以再引用i时, i==3

上例的最终输出为:

啊哈C:

i=6,  j=-40
7, 8
8

VC++6.0

i=6,  j=-40
7, 7
8

 TC7

i=6,  j=-40
7, 6
8

 从以上三个编译器来看, vc++6.0, 函数参数是从左向右处理, tc7是从右向左处理, 并且都把函数调用做为表达式求值来处理, 也就是在函数调用(表达式求值)完成后, 再执行i+=1

只有啊哈C, 在函数调用完成前, 第二个参数传值完成后, 就执行i+=1 //18-08-06补充

 

7. 数组变量的概念还有些不清晰

   int a[]={1, 3, 5};

  数组变量是说a吗?  不是, 数组变量a应该是说存放{1, 3, 5}这三个数的"特定的"的那片内存

  那么a是什么?一个可能, 是个只读型的指针变量,存放着这片内存的首地址(必须是只读,因为需要始终对应这个首地址)

 

a就只是一个指针, 用于不同表达式, 会有不同的效果

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值