当前位置:网站首页>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,可以发现一维的指针数组实现了二维数组的效果。
边栏推荐
- RTKLIB: demo5 b34f. 1 vs b33
- Data manipulation language (DML)
- Record: solution of 404 error of servlet accessing database in dynamic web project
- TYUT太原理工大学2022软工导论简答题
- XV Function definition and call
- 阿里云微服务(一)服务注册中心Nacos以及REST Template和Feign Client
- 12 excel charts and arrays
- 13 power map
- 凡人修仙学指针-2
- [GNSS] robust estimation (robust estimation) principle and program implementation
猜你喜欢

System design learning (I) design pastebin com (or Bit.ly)

(超详细onenet TCP协议接入)arduino+esp8266-01s接入物联网平台,上传实时采集数据/TCP透传(以及lua脚本如何获取和编写)

Tyut Taiyuan University of technology 2022 "Mao Gai" must be recited

How do architects draw system architecture blueprints?

西安电子科技大学22学年上学期《基础实验》试题及答案

Alibaba cloud microservices (II) distributed service configuration center and Nacos usage scenarios and implementation introduction

Inheritance and polymorphism (I)

系统设计学习(二)Design a key-value cache to save the results of the most recent web server queries

Edit distance (multi-source BFS)

Chromatic judgement bipartite graph
随机推荐
Decomposition relation model of the 2022 database of tyut Taiyuan University of Technology
Heap sort [handwritten small root heap]
View UI Plus 发布 1.3.0 版本,新增 Space、$ImagePreview 组件
阿里云微服务(四) Service Mesh综述以及实例Istio
几道高频的JVM面试题
12 excel charts and arrays
TYUT太原理工大学2022软工导论大题汇总
Pride-pppar source code analysis
RTKLIB: demo5 b34f. 1 vs b33
2-year experience summary, tell you how to do a good job in project management
阿里云微服务(一)服务注册中心Nacos以及REST Template和Feign Client
Inheritance and polymorphism (Part 2)
System design learning (I) design pastebin com (or Bit.ly)
Fgui project packaging and Publishing & importing unity & the way to display the UI
[while your roommate plays games, let's see a problem]
Ten minutes to thoroughly master cache breakdown, cache penetration, cache avalanche
Counter attack of flour dregs: redis series 52 questions, 30000 words + 80 pictures in detail.
记录:动态Web项目servlet访问数据库404错误之解决
Detailed explanation of balanced binary tree is easy to understand
阿里云一面:并发场景下的底层细节 - 伪共享问题