指针
- 指针是内存中一个最小单元的编号,也就是地址。
- 平时口语中说的指针,通常指的是指针变量。通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量。
int main()
{
int a = 10;//在内存中开辟一块空间
int* p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个之指针变量。
return 0;
}
总结:
指针变量,用来存放地址的变量(存放在指针中的值都被当成地址处理)。地址是唯一标示一块地址空间的。
- 一个小的单元是1个字节。
- 一个字节对应一个地址。
- 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。
- 在64位机器上,有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
指针类型
意义:
- 指针的类型决定了对指针解引用的时候有多大的权限(能操作几个字节)。比如,char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
- 指针的类型决定了指针向前或者向后走一步有多大(距离)。
野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。
1.未初始化
#include <stdio.h>
int main()
{
int *p;//p是一个局部变量指针,如果未初始化的话,默认为随机值
*p = 20;//非法访问内存
return 0;
}
结果:
2.越界访问
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=10; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0; }
3.指针指向的空间释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
*p = 20;
return 0;
}
如何规避野指针:
- 指针初始化。当不知道指针应初始化为什么地址的时候,直接初始化为NULL。
- 小心指针越界。C语言本身不会检查指针的越界行为。
- 指针指向空间释放,即使置NULL。
- 指针使用之前检查有效性
- 避免返回局部变量的地址
指针运算
1.指针 ± 整数
2.指针 - 指针:两个指针之间的元素个数(前提:两个指针指向同一块空间)
3.指针的关系运算
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里就是二级指针 。
指针数组
本质:是数组。是存放指针的数组。
结构体
结构:是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
- 结构的成员可以是标量、数组、指针,甚至是其他结构体。
- 结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。
- 结构体指针访问指向变量的成员有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。
- 结构体传参的时候,尽量要传结构体的地址。
函数调用的参数压栈
- 栈,是一种数据结构。先进后出,后进先出。
- 每一个函数的调用,都会在内存的栈区上开辟一块空间。
(欢迎大家批评指正,侵权即删!!!)