当前位置:网站首页>9.指针(上)
9.指针(上)
2022-07-06 09:19:00 【是王久久阿】
目录
1.指针是什么?
指针?什么是指针?从根本上来看,指针(pointer)是一个值为内存地址的变量(或数据对象)。正如char类型变量的值是字符,int类型变量的值是整数,指针变量的值是地址。平时口语中所说的指针通常指的就是指针变量,用来存放地址的变量。
int main()
{
int num = 10;
int* p = #
printf("%p\n", p);
return 0;
}
- 上述代码中,&为取地址符号,将变量num的地址取出来赋给p。
- *表示声明的变量是一个指针,而int表示指针的类型是整型;int*p的意思是,p是一个指针,*p是int类型。
- 利用printf函数打印地址时,%p对应的是地址。
以X86环境下运行上述代码,结果如下:
009BFA40是以16进制表示的,变量num就存放在该地址中。
就像我们生活中的地址一样,C语言中的地址也是唯一的。
2.指针的大小
既然指针作为存储地址的变量,那么计算机必然也会开辟出一块空间用来存放指针。
以上述代码为例,通过sizeof可以计算指针的大小:
int main()
{
int num = 10;
int* p = #
printf("%d\n", sizeof(p));
return 0;
}
在X86环境下,即32位机器中:指针占4个字节。
在X64环境下,即64位机器中:指针占8个字节。
1个字节等于8个比特位,那么32位机器中,指针可以表示2^32个地址;64位的机器中,则可以表示2^64个地址。
指针中最小的单元是字节,这是经过缜密的思考与权衡的。即我们可以查询一个char类型的字符的地址,但是无法查询这个字符中某一位的地址。
3.指针的类型
在创建一个变量时,我们需要为其声明类型,例如:用整型表示年龄,float类型表示身高、体重等;创建指针时也是如此,针对不同类型的变量,声明对应类型的指针来存放其地址。
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
(*和指针名之间的空格可有可无,不影响使用)
指针解引用(*)
通过间接运算符 *(indirection operator)可以用过地址来更改变量,该操作也称之为“解引用”。
#include<stdio.h>
int main()
{
int num = 10;
printf("改变前:%d\n", num);
int* p = #
*p = 2;
printf("改变后:%d\n", num);
return 0;
}
我们没有直接改变num的值,而是找到num存放的地址,通过解引用操作间接改变了num的值。
指针+-整数
#include<stdio.h>
int main()
{
int num = 10;
int* pi = #
char* pc = (char*)#
printf("%p\n", &num);
printf("%p\n", pi);
printf("%p\n", pi + 1);
printf("%p\n", pc);
printf("%p\n", pc + 1);
return 0;
}
表达式char* pc = (char*)&num:将整型变量num的地址取出来,强制转换成char*类型,然后赋给char*类型的指针变量pc。
通过测试发现:指针类型对应了指针+-时的跨度,即char类型的指针+1往后访问1个字节,int类型的指针+1往后访问4个字节。
4.野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
野指针成因
指针未初始化
#include <stdio.h>
int main()
{
int* p;
*p = 10;
return 0;
}
局部变量指针未初始化,默认为随机值。
指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 11; i++)
{
*(p++) = i;
}
return 0;
}
数组arr的下标为0~9,当指针指向的范围超出数组arr的范围时,p就是野指针。
指针指向的空间释放
当指针指向的变量被释放后,指针就是野指针了。
规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性(avoid)
#include <stdio.h>
#include <assert.h>
int main()
{
int* p = NULL;
int a=10;
int* p = &a;
assert(p != NULL);
*p = 10;
if(p!=NULL)
*p = 20;
return 0;
}
5.指针的运算
指针的运算关系
#include<stdio.h>
#define N 5
int main()
{
int ch[N] = { 0 };
int* vp;
for (vp = &ch[0]; vp < &ch[N];)
{
*vp++ = 1;
}
return 0;
}
- 表达式vp = &ch[0]表示将数组中首元素的地址赋给vp。
- vp < &ch[N]表示将vp中存放的地址与数组后一个元素的地址进行对比,只要vp小于它,就说明依然在数组中访问,没有越界。
- *vp++实际上是*(vp++),每次向后访问一个整型。
指针-指针
#include<stdio.h>
int my_strlen(char* s)
{
char* p = s;
while (*p != '\0')
p++;
return p - s;
}
int main()
{
char ch[]="hello";
printf("%d\n", my_strlen(ch));
return 0;
}
标准规定
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
6.指针和数组
这部分内容专门开了一章来讲,请看数组、指针和数组的关系。
7.二级指针
指针变量也是变量,是变量就必然会有存放的地址。那么存放指针变量地址的指针,就称为二级指针。
#include<stdio.h>
int main()
{
int a = 10;
int* p1 = &a;
int** p2 = &p1;
**p2 = 20;
return 0;
}
8.指针数组
指针数组是数组,只不过是用来专门存放指针的数组。
#include<stdio.h>
int main()
{
int arr1[] = {1,2,3};
int arr2[] = {4,5,6};
int arr3[] = {7,8,9};
int* p1 = arr1;
int* p2 = arr2;
int* p3 = arr3;
int* p[] = { p1,p2,p3 };
return 0;
}
int* p[] = { p1,p2,p3 }表示数组中存放数据的类型是int*类型,存放的数据分别是p1,p2,p3。
int i = 0, j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("%d ", *(*(p + i))+j);
}
putchar('\n');
}
建立两个for循环打印指针数组p,可以发现一维的指针数组实现了二维数组的效果。
边栏推荐
- 图书管理系统小练习
- TYUT太原理工大学2022软工导论大题汇总
- [Topic terminator]
- View UI Plus 發布 1.3.1 版本,增强 TypeScript 使用體驗
- 记录:初次cmd启动MySQL拒接访问之解决
- Differences and application scenarios between MySQL index clock B-tree, b+tree and hash indexes
- C code implementation of robust estimation in rtklib's pntpos function (standard single point positioning spp)
- Novatel board oem617d configuration step record
- 阿里云微服务(四) Service Mesh综述以及实例Istio
- Experience summary of autumn recruitment of state-owned enterprises
猜你喜欢
View UI plus released version 1.2.0 and added image, skeleton and typography components
国企秋招经验总结
TYUT太原理工大学2022数据库大题之数据库操作
The port is occupied because the service is not shut down normally
几道高频的JVM面试题
Conceptual model design of the 2022 database of tyut Taiyuan University of Technology
系统设计学习(二)Design a key-value cache to save the results of the most recent web server queries
阿里云微服务(四) Service Mesh综述以及实例Istio
Decomposition relation model of the 2022 database of tyut Taiyuan University of Technology
阿里云微服务(一)服务注册中心Nacos以及REST Template和Feign Client
随机推荐
错误:排序与角标越界
Introduction and use of redis
Voir ui plus version 1.3.1 pour améliorer l'expérience Typescript
TYUT太原理工大学2022数据库大题之概念模型设计
IPv6 experiment
How to ensure data consistency between MySQL and redis?
TYUT太原理工大学2022数据库大题之数据库操作
All in one 1405: sum and product of prime numbers
几道高频的JVM面试题
Alibaba cloud side: underlying details in concurrent scenarios - pseudo sharing
TYUT太原理工大学2022软工导论考试题型大纲
TYUT太原理工大学2022数据库考试题型大纲
Fundamentals of UD decomposition of KF UD decomposition [1]
The earth revolves around the sun
Problems and solutions of robust estimation in rtklib single point location spp
Dark chain lock (lca+ difference on tree)
Edit distance (multi-source BFS)
Tyut Taiyuan University of technology 2022 introduction to software engineering
初识指针笔记
TYUT太原理工大学2022“mao gai”必背