概述
C语言指针一览表
文章目录
- C语言指针一览表
- 一、指针的概念
- 1、内存与地址
- 2、一级(二级)指针的概念
- 二、野指针的概念
- 1、概念
- 2、成因
- 3、如何规避上诉问题?
- 三、六大基本指针类型
- 1、char*
- 2、short*
- 3、int*
- 4、long*
- 5、float*
- 6、double*
- 四、指针运算
- 1、& 与 *
- 2、指针 +- 整数
- 3、指针 - 指针
- 4、const int* p 与 int* const p
- 五、指针与数组
- 1、指针数组
- 2、数组指针
- 3、一维数组传参
- 4、二维数组传参
- 六、函数指针
- 回调函数
- 七、总结
一、指针的概念
1、内存与地址
随着科技的进步,人们的生活也在发生改变,电子产品也是!
我们常听说,某某的新买的电脑是64位的,某某的电脑是32位。这里说的“位”,实则是中央处理器(CPU)的字长,作用呢,就是 CPU一次能够处理二进制数
的最大位数。
现在主流电脑都是32位或者64位,这跟我们所说的内存有关系吗?
当然有! 举个栗子:
小明和小芳是高中同学,过几天呢,就是小芳的18岁生日,小芳就邀请小明去她家一起庆祝生日。小明心想“这感情好啊,直接去她家过生日!!!”,说:“小芳芳,你家在重庆哪儿呢?”
“咳咳,别走远了”
“在**滨江路250号**,你星期天过来吧!”,小芳说;
“不要想太多,重心不在其他事上!”
上文,提到了*滨江路250号*,这就是一个地址啊,小明可以通过这个地址找到小芳芳家。我们的电脑也是可以通过“地址”找到一块内存空间的。
如图:
重点:
- 32位电脑的内存地址范围是 0 ~ 232 - 1
- 64位电脑的内存地址范围是0 ~ 264 -1
- 每一个单位的内存空间的大小是 1个字节
- 字长不同的电脑,指针所占空间的大小也不一样,32位电脑上,一个指针变量占 4个字节,64位电脑上,占 8个字节
2、一级(二级)指针的概念
指针?什么是指针?
从根本上看,指针(pointer)是一个值为内存地址的变量(或数据对象)。正如char类型变量的值是字符,int类型变量的值是整数,指针变量的值是地址。
int a = 20; //整形变量
int* p1 = &a; //一级指针
int** p2 = &p1; //二级指针
上述p1与p2就是两个指针变量,先看p1,p1变量的类型是 int*
, int* 就代表它是一个一级指针。
再看p2,p2变量的类型是int**
,有两颗星,就代表这是个二级指针,再看它的值是 &p1
,是取的一级指针的内存地址。也就是说,1. 二级指针 指向的是一个 一级指针; **2.**一级指针指向的是基本数据类型,int、char、short等。
二、野指针的概念
1、概念
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。
2、成因
a. 指针未初始化,如下
int main()
{
int a = 10;
int* p1 = &a; //正确,把a的内存地址赋值给p1
int* p2; //错误,未初始化,若直接进行访问,会报错
return 0;
}
b. 指针越界访问,如下
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int* p = arr; //数组名,首元素地址
for (int i = 0; i < 11; i++)
{
printf("%d ",*(p+i)); //数组元素共10个,最后一个元素的下标是9,i变量能够等于10,越界
printf("%d ",arr[i]); //此处两个printf函数的作用,等价
}
return 0;
}
c.指针指向的内存空间已经被释放,如下
struct Student
{
char name[20];
int age;
};
int main()
{
//创建一个结构体,返回的是指向 struct Student类型的指针变量 s1
struct Student* s1 = (struct Student*)malloc(sizeof(struct Student));
//假设现在我们不需要这块空间了,在C/C++中,malloc申请的内存空间需要程序员自己手动释放(回收)
free(s1);
//现在s1已经被释放(回收)了,意思是 由变量s1指向的这块内存空间还给了系统
//但是s1里面还是保存着这块内存空间(struct Student)的内存地址(可理解为房间号)
//如果此时再次去访问这块空间,那就会出错的。因为这块空间已经回收了
s1->name = "博尔特"; //错误,内存空间已经回收,这也称为也指针
return 0;
}
3、如何规避上诉问题?
有人说:“不使用指针,就完美的规避了”。 那不可能啊,衡量一个C/C++程序员的技术水平,指针的运用占了不小的份额。
- 指针初始化
- 小心指针越界访问
- 指针指向的空间释放后,及时置为NULL
- 指针使用之前检查有效性
三、六大基本指针类型
1、char*
char ch = 'A';
char* p = &ch; //将ch的内存地址赋值给p
2、short*
short a = 1314;
short* p = &a; //将a的内存地址赋值给p
3、int*
int a = 10;
int* p = &a; //将a的内存地址赋值给p
4、long*
long a = 100000;
long* p = &a; //将a的内存地址赋值给p
5、float*
float a = 3.0;
float p = &a; //将a的内存地址赋值给p
6、double*
double a = 5.0;
double* p = &a; //将a的内存地址赋值给p
四、指针运算
1、& 与 *
&: 取地址符,可以取出变量在内存中的地址。
示例: &number, 取出number变量的内存地址
**:**间接访问操作符,也叫解引用,不要与二元运算符()混淆,二者符号相同,但语法不同。
int main()
{
int a = 20;
int* p = &a; //取a的地址
printf("%dn",*p); //通过指针p,进行解引用,去输出a的值
return 0;
}
2、指针 ± 整数
int main()
{
char arr1[5] = {'a','b','c','d','e'};
int arr2[5] = {1, 2, 3, 4, 5};
char* p1 = arr1;
int* p2 = arr2;
for (int i = 0; i < 5; i++)
{
printf("%c ",*(arr1 + i));
}
for (int i = 4; i >= 0; i--)
{
printf("%d ", *(arr2 + i));
}
return 0;
}
上诉代码输出的结果是
a b c d e
5 4 3 2 1
char类型的变量占一个字节的空间,int类型的变量占四个字节的空间。而两个指针变量p1和p2也能够加减一个整数去读取内存中的数据。
也就是说,int* 的指针p2 + 1 ,并不是向后访问一个字节空间,而是访问的int类型的4个空间。例如:short* 的指针变量 p+1,向后访问的是short类型的2个空间,如下图int*类型指针加减的过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V4KIv7Zh-1622041026120)(asserts/%E5%8A%A8%E7%94%BB.gif)]
3、指针 - 指针
int my_strlen(char *s) {
char *p = s;
while(*p != '