【0006】左值、右值和const与内存实体的联系

赋值号左边的叫做左值,赋值号右边的叫右值

左值都在内存中,有内存实体;右值一般在寄存器中,左值也可作为右值

void main024()
{
    int a = 1;
    //&(a + 2);                &取内存地址(&在CPU中完成),而a+2位于寄存器中
    a = a + 3;                
    /*
        a = a + 3;    的计算过程:
            1、数值1位于代码区的常量符号表中,CPU将1复制到寄存器变量
            2、CPU中的控制器根据变量a的内存地址,将寄存器中的1赋值给内存变量a,此时内存变量a存储的值为1
            3、a+3,CPU根据内存变量a的地址复制其值到寄存器,加法器将位于代码区的常量符号表中3与寄存器中的1进行加法运算,其值保存在此寄存器中
            4、重复步骤2,内存变量a的地址存储的值变为4

        左值都在内存中,有内存实体;右值一般在寄存器中,左值也可作为右值
    */

    int b = 10;
    int c = 20;
    printf("b=%p, c=%p 
", &b, &c);

    int *p = NULL;        // p是一个变量

    p = &b;

    p = &c;

    system("pause");
}
int a=1, a=a+3; 在计算机中的运算过程

变量与地址的联系

void main026()
{
    int *p = NULL;
    int a = 3;

    printf("%p 
", &a);        // 005DFCC0

    int b = &a;

    p = b;

    printf("%d 
", *p);        // 3

    int *px = (int *)0x005DFCC0;        // 给指针指定地址
    *px = 6;
    printf("%d 
", a);            // 6

    system("pause");
}
变量与地址的联系

空类型指针与变量的联系

void main027()
{
    int *p = NULL;            // 指针为空

    int num = 20;
    void *pv = #        // pv为空类型指针,可以容纳任何类型的指针
    //*pv;                    // error C2100: illegal indirection,其解析方式不确定,步长不确定
    printf("%d 
", *(int *)pv);    // 20    
    /*
        通过强制类型转换可以实现数据访问
            pv是一个void *空类型指针,步长不确定,解析方式也不确定
            (int *)pv,表达式(强制类型转换后)是一个int *类型的变量,步长为4,采用整型int类型的方式对pv指向的4字节数据进行int类型解析访问
    */

    system("pause");
}
空类型指针与变量的联系

有关键字修饰的变量声明,这个变量称为伪常量;在代码中一般作为一个常量看待,只能声明的时候初始化该变量,便于代码的修改

但是改变量之所以叫做伪常量,是因为该变量可以在内存中被修改,或者通过间接的方式对变量进行修改

void main025()
{
    const int num = 3;        // num是一个左值,是一个伪常量,可以通过间接的方式对其值进行修改

    //*(&num) = 5;            error C2166 : l - value specifies const object

    *(int *)(&num) = 5;        // &num是一个const int *类型的指针变量,(int *)进行强制类型转换

    printf("%d 
", num);    // 5

    system("pause");
}
间接方式修改伪常量的值

声明指针变量时关键字const的修饰对指针的影响

关键字const修饰的指针声明:
     1、【指向常量的指针】int const *pconst int *p 时(*在后面),指针指向的值不能改变,指针的指向可以改变 —— 查询报表(常看多个账户数据)                    
     2、【指向变量的常量指针】int * const p (*在前面),指针指向的值可以改变,指针的指向不能改变 —— 可以查询并修改当前用户的数据                                        
     3、【指向常量的常量指针】int const * const p const int * const p (*的左右两边都有),指针指向的数据和指针存储的地址都不能改变 —— 代理查询,只能查看当前账户的数据

// 给与只读权限
void select(const int *p)        // int const *p 和 const int *p等价
{
    //*p = 10000;                //    error C2166: l-value specifies const object
    printf("银行有%d元 
", *p);
}
void main006()
{
    int num1 = 101;
    select(&num1);

    int num2 = 102;
    int num3 = 103;

    const int *p = &num2;
    //num2 = 112;
    //printf("%d, %d 
", num2, *p);        // 112, 112

    p = &num3;
    //*p = 113;            // error C2166: l-value specifies const object

    system("pause");
}
int const *p 只读权限
// 只允许当前账户操纵当前账户
void main007()
{
    int num2 = 102;        // 账户2的存款
    int num3 = 103;        // 账户3的存款

    int * const p = &num2;
    *p += 222;
    printf("%d 
", num2);    // 324

    //p = &num3;            // error C2166: l-value specifies const object

    system("pause");
}
int * const p
void main008()
{
    int num = 100;
    int num1 = 1023;

    const int * const p = #
    printf("%d 
", *p);            // 100

    /*p = 101234;            指向的数据和指针的存储地址都不能改变
    *p = &num1;*/

    system("pause");
}
const int * const p
void main009()
{
    int a[5] = { 1,2,3,4,5 };
    int *p = a;
    int * const px = a;            // 数组名的本质是指向变量的常量指针
    *(a + 3) = 6;
    printf("%d", a[3]);            // 6
    /*a = 1;
    px = 1;*/

    system("pause");
}
int * const px == a 数组名的本质是指向变量的常量指针
原文地址:https://www.cnblogs.com/ant-colonies/p/13395117.html