当前位置:网站首页>(primary) pointer
(primary) pointer
2022-08-05 18:22:00 【I'm going ashore~】
好长时间没有更新博客了,The blogger considered his own learning route some time ago,Still want to go to graduate school,It will be updated in the future.
This article briefly explains some of the basics of pointers,The big move will also be placed in the back.
目录
1. 指针是什么?
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
#include <stdio.h>
int main()
{
int a = 10;//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符.
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
中,p就是一个之指针变量.
return 0;
}指针变量,In fact, it is a variable used to store an address.(存放在指针中的值都被当成地址处理)
那这里的问题是:
一个小的单元到底是多大?(1个字节)
如何编址?
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的.
对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111所以这里就有2的32次方个地址.
每个地址标识一个字节,那我们就可以给 (2^32Byte == 2^32/1024KB ==
2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB) 4G的空闲进行编址.
同样的方法,那64位机器,如果给64根地址线,那能编址多大空间,自己计算这里我们就明白:
在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节.那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址.
总结:
指针是用来存放地址的,地址是唯一标示一块地址空间的.
指针的大小在32位平台是4个字节,在64位平台是8个字节
2. 指针和指针类型
这里我们在讨论一下:指针的类型
我们都知道,变量有不同的类型,整形,浮点型等.那指针有没有类型呢?
准确的说:有的. Here we give some pointers of different typeschar *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;char* 类型的指针是为了存放 char 类型变量的地址.
short* 类型的指针是为了存放 short 类型变量的地址.
int* 类型的指针是为了存放 int 类型变量的地址
那指针类型的意义是什么?
2.1 指针+-整数
#include <stdio.h>
int main()
{
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
return 0;
}
总结:指针的类型决定了指针向前或者向后走一步有多大(距离).
2.2 指针的解引用
int main()
{
int n = 0x11223344;
int* pi = &n;
*pi = 0;
char* pa = &n;
*pa = 0;
return 0;
}
int main()
{
int a = 10;
int*pa = &a;
char* pc = &a;
printf("%p\n", pa);
printf("%p\n", pc);
printf("%p\n", pa+1);
printf("%p\n", pc+1);
return 0;
}
总结:
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节).
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节.
3. 野指针
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1 野指针成因
1. 指针未初始化
The address pointed to by this pointer is unknown,Maybe it's not yours yet.所以将20wrong to put in.
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}2. 指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
} 3. 指针指向的空间释放
这里放在动态内存开辟的时候讲解,A brief mention here.
int* test()
{
int a = 10;
printf("%d\n", a);
return &a;
}
int main()
{
int* p = test();
*p = 100;
return 0;
}test函数调用后,虽然把a的地址交给了p,但是aThe address of this variable is returned to the operating system,这样pThe pointer points to an unknown area again.
3.2 如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
#include <stdio.h>
int main()
{
int *p = NULL;
//....
int a = 10;
p = &a;
if(p != NULL)
{
*p = 20;
}
return 0;
}4. 指针运算
4.1 指针+-整数
#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
*vp++ = 0;
}
4.2 指针-指针
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[0] - &arr[9]);
return 0;
} 
指针-指针,The premise is that the two pointers must point to the same space,The absolute value of the value they get is the number of elements between the two pointers.但是char ch [5],int arr[6] , &arr[3] - &ch[4] 这种写法是错误的.
实现strlen函数,applied examples.
int my_strlen(char* str)
{
char* start = str;
while (*str)
{
str++;
}
return str - start;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}4.3 指针的关系运算
for(vp = &values[N_VALUES]; vp > &values[0];)
{
*--vp = 0;
}代码简化, 这将代码修改如下:
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
*vp = 0;
}
实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与
指向第一个元素之前的那个内存位置的指针进行比较.
5. 指针和数组

数组名表示的是数组首元素的地址.
但是有2个例外:
sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小
&数组名,数组名表示整个数组,取出的是整个数组的地址
既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5 6 7 8 9
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
}
//printf("%p\n", arr);//
//printf("%p\n", &arr[0]);
//printf("%d\n", sizeof(arr));
return 0;
}所以 p+i 其实计算的是数组 arr 下标为i的地址.那我们就可以直接通过指针来访问数组.
6. 二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
这就是 二级指针.

对于二级指针的运算有:
*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .
int b = 20;
*ppa = &b;//等价于 pa = &b;**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;
int arr1[5];
char arr2[6];7. 指针数组
指针数组是指针还是数组?
答:是数组.是存放指针的数组
int main()
{
int data1[] = { 1,2,3,4,5 };
int data2[] = { 2,3,4,5,6 };
int data3[] = { 3,4,5,6,7 };
//arr就是一个指针数组
int* arr[3] = { data1 ,data2, data3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
边栏推荐
猜你喜欢

译文推荐|深入解析 BookKeeper 协议模型与验证

2022CISCN华东北复现

The pit of the date selection box of vnt design: a-range-picker has selected the time verification, but it still fails??

金仓数据库 KingbaseES V8 GIS 数据迁移方案(5. 第三方通用格式 GIS 数据迁移到 KES)

4、常用样式

分析LED透明屏VS常规显示屏优劣

MetaFormer/PoolFormer学习笔记及代码

齐岳|超支化聚缩水甘油接枝磁性Fe3O4纳米粒子(HPG-grafted MNPs)

一个很好用的中奖概率控制器

金仓数据库 KingbaseGIS 使用手册(4. 数据管理和查询)
随机推荐
uniapp中用canvas实现小球碰撞的小动画
力扣每日一题-第49天-724. 寻找数组的中心下标
CentOS7安装MySQL8
金鱼哥RHCA回忆录:CL210管理计算资源--课外普及之Nova组件详解
PEG化四氧化三铁纳米颗粒(氨基末端)NH2-PEG-Fe3O4
译文推荐|Apache Pulsar 隔离系列(四):单集群隔离策略
1.报表平台规划
包载信使mRNA的多西环素纳米脂质体|雷公藤红素纳米脂质体RNA核糖核酸(实验原理)
1.9 亿美元被“掏空”!黑客牵头,路人“趁火打劫”,一切仅因一个低级致命漏洞...
BHQ淬灭试剂BHQ-2 acid|cas:1214891-99-2|BHQ-2 酸|BHQ-2 羧基的信息你知道多少
金仓数据库 KingbaseES 客户端编程接口指南 - JDBC(11. JDBC 示例说明)
Golang 汇编asm语言基础学习
调用colmap作为my项目第三方库,debug进入colmap代码调试--CMakeLists配置
在GridView中对于有外键的字段使用关联模型进行搜索和排序
JVM-第三章 运行时数据区概述及线程
一套多用表单小部件代码下载
金仓数据库 KingbaseES V8 GIS 数据迁移方案(5. 第三方通用格式 GIS 数据迁移到 KES)
小就是大|2022 OceanBase 年度发布会亮点抢先看!
国标视频云服务EasyGBS如何正确调阅实时录像接口?
nacos和eruka的区别