1.内存与地址
- 计算机CPU处理数据时,所需数据是从内存中读取的,处理后的数据也会放回内存中,而内存管理的方式就是把内存划分为一个个的内存单元,每个内存单元占一个字节,并且每个内存单元都有相应的编号(比如我们的宿舍都有相关编号,这样方便我们通过编号找到相应宿舍,也方便管理,而一个字节等于8个比特位,相当于每一个宿舍都有8个学生),这样方便CPU找到需要处理的数据。
- C语言中 地址=指针=内存单元编号
2.指针变量与地址
1.&符号(取地址操作符)
&符号用于得到对应变量的地址
#include<stdio.h>
int main()
{
int a=4; //整型占4个字节
printf("%p",&a);
return 0;
}
&a取出的是a所占4个字节中地址较小的字节的地址
虽然整型变量占四个字节,但是我们只要知道了一个字节的地址,顺藤摸瓜也可以访问到四个字节
2.指针变量和解引用操作符(*)
- 指针变量:用于存储地址的值(也就是内存单元的编码)
- 指针变量也是一种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会被理解为地址
int a=4;
int* p=&a;
- int* 是指指针变量的类型,也就是p的类型,int 是指p所指向的对象的类型
- * 解引用操作符:可以通过地址找到地址所指向的对象(只是地址所指向的地方对应的值,而不是某个变量)
int a=100; int *pa=&a; *pa=0;
- 这里a的地址是pa,而解引用操作符把pa所指向的地方找到,并且修改,此时a地址是pa,所以a的值就改变了
-
指针变量的大小:指针变量大小取决于地址大小,32位平台下是32个比特位,64位平台下是64个比特位。注意指针变量大小与类型无关,在相同平台下,大小都是相同的
3.指针变量类型的意义
1.指针的解引用
//代码1
int n=0x11223344;
int* p=&n;
*p=0;
//代码2
int n=0x11223344;
char* p=&n;
*p=0;
调试我们可以看到,两段代码对比可以看到代码一通过解引用改变了四个字节的内容,而代码二通过解引用只改变了一个字节
结论:指针的类型决定它对几个字节有权限。
2.指针+-整数
所以,指针的类型也决定了指针向前或者向后走一步有多大(多少个字节)
3.void*指针
-
是无具体类型的指针,可以接受任意类型指针,但是不可以直接进行解引用操作,也不能进行+-运算
-
int类型的变量的地址不能赋值给char*指针,而使用void*不会有这种不兼容问题
4.const修饰指针
1.修饰变量
const int n=20;
n=1;//n不能被修改,不符合语法规则
n本质为变量,是可以修改的,不过加上了const之后,语法受到了限制,不能直接修改n变量
int*p=&n;
*p=0;
但是可以通过地址修改n变量
2.修饰指针变量
- const放在 * 的左边时,修饰的是*p,保证指针指向的内容不能改变,但是指针变量本身可以改变
- const放在 * 的右边时,修饰的是p,保证指针的指向不变,即p不变,但是指针指向的内容可以改变
5.指针运算
1.+-整数运算
可以根据运算的指针变量的类型看整数的加减是操作几个字节
2.指针+-运算
两个指针相减一般用于需要一个指针移动时,通过初末指针的位置差判断移动了几个单位(两个指针类型要相同,每个单位大小为它们指向的对象的大小)
3.指针的关系运算
实际上就是比较指针变量(内存单位编号)的大小,一般用于循环
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
while (p < arr + sz)
{
printf("%d ", *p);
p++;
}
return 0;
}
6.野指针
野指针就是指针指向的位置是不可知的,随机的,不正确的,没有明确限制的
1.原因
- 指针未初始化
- 指针越界访问
- 指针指向的空间释放
2.如何规避野指针
- 指针初始化
- 小心指针越界
- 指针不再使用时,即使置NULL
- 避免返回局部变量地址
7.assert断言
由头文件 assert.h 包含
assert(p!=NULL);
若括号内返回为假,直接报错,中断程序
如果已经确认程序没有问题,可以加预处理 #define DEBUG 编译器会禁止用一切assert语句
8.指针的使用和传值调用
当我们定义一个函数时,如果形参不是指针,而只是一个变量,那么形参只会拷贝一份与实参大小相同的变量,当函数调用结束,形参被销毁,实参不会受到影响
#include<stdio.h>
void swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int x = 2;
int y = 3;
swap(x, y);
return 0;
}
这个时候我们可以使用指针,通过地址改变它们的值
#include<stdio.h>
void swap(int* px, int* py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int x = 2;
int y = 3;
int* px = &x;
int* py = &y;
swap(px, py);
printf("%d %d ", x, y);
return 0;
}
此时调试运行一下就知道两个变量的值改变了