一.内存和地址
计算机上CPU(中央处理器)处理数据时,需要的数据从内存中读取,处理完的数据也会放回内存中。
1.内存的使用和管理
内存是一块块存储数据的空间,最小结构是内存单元,内存单元的大小是1Byte。
内存是有编号的,计算机是通过内存的编号找到内存,内存的编号就是地址,而在C语言中,地址又叫指针。
(1)计算机中的单位:1Byte = 8bit
(2)地址总线
a.计算机中数据在各硬件之间的传递,是通过线来实现的
有:数据总线,地址总线,控制总线
b.地址不需要记录被存储在内存中
32位机器,有32根地址总线,每一根总线有两种电脉冲状态(地址不需要记录),抽象化用数字0、1表示电脉冲两种状态,总共就可以表示2^32种含义。
二.指针
1.指针变量(存放指针的变量)
(1)指针变量的创建
a.
int a = 2;
char ch = 'c';
int* pa = &a;//pa指针变量
//*表示pa是指针,int表示pa指向的对象a是int类型,int*表示pa的类型
//&取地址操作符,取出a的地址赋给pa
//int类型占四个字节,取地址取的是首字节地址
char* pc = &ch;//pc指针变量
//*表示pc是指针,char表示pc指向的对象ch是char类型,char*表示pc的类型
//&取地址操作符,取出ch的地址赋给pc
printf("a = %d,*pa = %d\n", a, *pa);
//*解引用操作符,*pa找到pa所指的对象a
printf("ch = %c,*pc = %c\n", ch, *pc);
//*解引用操作符,*pc找到pc所指的对象ch
b.
创建变量的本质:向内存申请空间,存放数据。
编译器不是通过变量名来找到内存单元,而是通过地址找到的。
(2)指针变量的大小
指针变量存放地址,地址有多大指针变量就有多大;
32位机器,有32根地址总线,地址大小为32bit,指针变量大小为四个字节;64位机器,有64根地址总线,地址大小为64bit,指针变量大小为八个字节;
指针变量的大小与指针指向的对象类型无关。
2.指针类型的意义
(1)解引用中,决定权限 ---- 访问空间大小
a.int*类型的指针解引用,访问的空间大小是四个字节
*pa改变a的大小,将四个字节全部置为了0
b.char*类型的指针解引用,访问的空间大小是一个字节
*pc改变pc的大小,只能将一个字节置为0
(2)指针加减整数时,决定指针前移,后移的长度
a.int*类型的指针加1,跳过4个字节
加n,跳过n * sizeof(int) 个字节
b.char*类型的指针加1,跳过1个字节
加n,跳过n * sizeof(char) 个字节
3.void*指针,无具体类型的指针
void*类型的指针可以接收任意类型的指针,不能直接加减整数和解引用(因为void*没有具体类型,不知道解引用访问的权限,不知道加减整数跳过的字节大小)
void*常用于函数的参数部分,实现泛型编程
4.const修饰指针
a.const修饰的变量,叫常变量,具有常量属性
int num = 100;
num = 200;
printf("%d",num);//打印出的值是200;
const int num = 100;
num = 200;//编译器会报错:表达式必须是可修改的左值
b.这个被修饰的变量本质上仍是变量,只是值不能被修改
const int n = 10;
char arr[n];//编译器会报错,C99之前数组大小是需要用常量或常量表达式来指定
c.const修饰指针
const在*左边还是右边,起的作用有差异
(1)const在*左边,限制指针变量本身,但指针指向的对象可以改变
int a = 10;
const int* pa = &a;//或者也可以写为int const* pa = &a;
*pa = 20;//编译器会报错,const在*左边,限制指针指向的对象,指针指向的对象不可以改变
int b = 15;
pa = &b;//const在*左边,指针变量本身可以改变,编译语法没问题,编译器不会报错
(2)const在*右边,限制指针指向的对象,但指针变量本身可以改变
int a = 10;
int* const pa = &a;
int b = 15;
pa = &b;//编译器会报错,const在*右边,限制指针变量本身,指针变量本身不能改变
*pa = 20;//const在*右边,指针指向的对象可以改变,编译语法没问题,编译器不会报错