当前位置:网站首页>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,可以发现一维的指针数组实现了二维数组的效果。
边栏推荐
- Heap sort [handwritten small root heap]
- Alibaba cloud side: underlying details in concurrent scenarios - pseudo sharing
- First acquaintance with C language (Part 1)
- IPv6 experiment
- Alibaba cloud microservices (I) service registry Nacos, rest template and feign client
- String类
- Tyut Taiyuan University of technology 2022 introduction to software engineering examination question outline
- TYUT太原理工大学2022“mao gai”必背
- 记录:动态Web项目servlet访问数据库404错误之解决
- 阿里云微服务(四) Service Mesh综述以及实例Istio
猜你喜欢

凡人修仙学指针-2

Data manipulation language (DML)

Redis介绍与使用

面渣逆袭:Redis连环五十二问,三万字+八十图详解。

Application architecture of large live broadcast platform

Common method signatures and meanings of Iterable, collection and list

Several high-frequency JVM interview questions

Counter attack of flour dregs: redis series 52 questions, 30000 words + 80 pictures in detail.

Novatel board oem617d configuration step record

Application architecture of large live broadcast platform
随机推荐
Voir ui plus version 1.3.1 pour améliorer l'expérience Typescript
初识C语言(上)
Branch and loop statements
View UI Plus 發布 1.3.1 版本,增强 TypeScript 使用體驗
[dry goods] cycle slip detection of suggestions to improve the fixed rate of RTK ambiguity
异常:IOException:Stream Closed
IPv6 experiment
Problems and solutions of robust estimation in rtklib single point location spp
Introduction pointer notes
记录:newInstance()过时的代替方法
[GNSS data processing] Helmert variance component estimation analysis and code implementation
记录:动态Web项目servlet访问数据库404错误之解决
Tyut Taiyuan University of technology 2022 "Mao Gai" must be recited
Code example of MATLAB reading GNSS observation value o file
2-year experience summary, tell you how to do a good job in project management
Relational algebra of tyut Taiyuan University of technology 2022 database
TYUT太原理工大学往年数据库简述题
Realization of the code for calculating the mean square error of GPS Height Fitting
Tyut outline of 2022 database examination of Taiyuan University of Technology
Summary of multiple choice questions in the 2022 database of tyut Taiyuan University of Technology