目录
1.指针的概念
指针:
1.指针是内存中一个最小单元的编号,也就是地址
2.平时口语中的指针说的是指针变量,是用来存放地址的变量
1.1指针变量
我们可以通过&(取地址符)取出变量的内存地址,把地址存放到一个变量里面,这个变量就是指针变量。
1.2电脑如何进行编址
实际从上图我们不难发现,一个小的内存单元就是一个字节,一个字节有一个对应的地址,就像生活中我们把一栋楼比喻为一块内存,那么每一户作为一个字节的小的内存单元,门牌号就是一个地址,我们只用通过门牌号就可以访问到每一户。
那么地址是如何产生的呢?
对于32位机器来说,会有·32根地址线,每根地址线在寻址的时候就会产生随机的高水平(高电压)和低水(低电压),也就是1和0.那么32根地址线产生的地址范围就是:
00000000 00000000 00000000 0000000000000000 00000000 00000000 00000001
...........
...........
111111111 11111111 11111111 11111111
产生2^32个地址,
那么如果我们给每个地址标识一个字节
2^32byte = 2^32/1024kb=2^32/1024/1024/1024 =4GB
就可以对4GB的内存进行编址
1.3指针变量的大小
1.在32位机器上,地址是32个0/1组成的二进制序列,那地址就得用四个字节的空间来存储,所以在32位机器上一个指针变量的大小就是四个字节。64位操作系统就是8个字节。
2.指针和指针类型
2.1指针类型
变量都有类型,那么作为指针也是有类型的。
指针变量的定义方式:
type * p
1.p 指的是指针指向对象的类型
2.*说明p是指针
3.type决定了指针p解引用的时候访问的对象的大小是sizeof(type)
比如:
char * 类型解引用访问的是1个字节的内容
int* 解引用访问的是4个字节的内容
我们来看一下实际例子:
int main()
{
int a = 0x11223344;//0x开头是16进制数字,一个16进制为换算4个二进制位。
char* p = &a;
*p = 0;
return 0;
}
我们看到char*l类型的指针解引用只改变了内存中一个字节的内容。
从上面例子就可以总结出指针类型的作用:
1.指针类型可以决定指针解引用的时候可以访问多少个字节(指针的权限)
2.2指针加减整数
附上源码大家体验效果:
int main()
{
int n = 0x11223344;
int* p1 = &n;
char* p2 = &n;
printf("%p\n", &n);
printf("%p\n", p1);
printf("%p\n", p2);
printf("%p\n", p1 + 1);
printf("%p\n", p2 + 1);
return 0;
}
那么是不是就可以得出结论:
指针类型决定了了指正+-整数时跳过的步长。
+-n就是跳过N*sizeof(type)
总结
1.指针的类型决定了,对指针解引用的时候能操作多少字节(指针的权限)
2.指针的类型决定了指针向前或者向后走一步有多少距离。
3.野指针
3.1野指针的成因
3.1.1 指针未初始化
int main()
{
int *p;//局部变量指针未初始化,默认为随机值*p = 20;
return 0;
}
3.1.2指针1越界访问
3.1.3 指针指向的空间释放了
这种访问是非法的
3.2 如何规避野指针
1.指针的初始化。当明确知道指针应该初始化为谁的地址就直接使用初始化;不知道指针初始化为什么指的时候,暂时初始化为NULL
2.避免和小心指针越界
3.指针指向空间释放,及时置NULL
4.避免返回局部变量的地址
5.指针使用之前检查有效性。
4.指针运算
4.1指针+-整数
4.2指针-指针
两个指针相减得到的值的绝对值的指针和指针之间的元素个数。
前提是:两个指针指向同一块空间。
指针减指针的应用可以用于实现strlen函数(不创建临时变量)
附上源码大家可以看一下效果:
int mystrlen(char* s)
{
char* str = s;
while (*s != '\0')
{
s++;
}
return s - str;//两个指向同一空间的指针相减得到两个指针之间预算个数
}
int main()
{
char arr[] = "abcdefwuh";
int len = mystrlen(arr);
printf("%d\n", len);
return 0;
}
4.3 指针的关系运算
地址是有大小的
指针的关系运算就是比较指针的大小
C语言标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
5.指针和数组
5.1
指针变量大小是固定的,4/8(专门用于存放地址)
数组是一组连续的空间,可以用于存放一个或者多个类型相同的数据
数组名是数组首元素的地址
数组名 == 地址==指针
把数组名当做地址放到指针里面,就可以实现用指针访问数组
对于数组来说,除了数组名就是数组的类型
int arr[10] 和 int arr[8] 的类型分别是int [10] 和int 【8】
附上源码,大家可以体验一下:
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d]=%p <==> p+%d = %p\n", i, &arr[i],i, p + i);
}
return 0;
}
5.2指针数组
指针数组是一个数组
整型数组--存放整型
字符数组----存放字符
指针数组---存放指针
6.二级指针
指针变量也是变量,是变量就有地址,指针变量的地址也可以存放在另外一个指针里,这个指针就称为二级指针。
7.后续会补充结构体指针。
以上就是C语言初阶的指针知识的整理,后面还会继续更新进阶指针的内容,也欢迎大家多多指正,共同进步。