赋值号左边的叫做左值,赋值号右边的叫右值
左值都在内存中,有内存实体;右值一般在寄存器中,左值也可作为右值

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"); }
变量与地址的联系

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 *p 或 const 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"); }

// 只允许当前账户操纵当前账户 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"); }

void main008() { int num = 100; int num1 = 1023; const int * const p = # printf("%d ", *p); // 100 /*p = 101234; 指向的数据和指针的存储地址都不能改变 *p = &num1;*/ system("pause"); }

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"); }