指针(2)进阶指针

接下来,我们介绍一下进阶指针:这里包括很多指针数组、数组指针、二级指针、函数指针等等。

常见类型

首先我们来说一下常见指针的类型:

  1. 指向整型的指针:int *
  2. 指向字符型的指针:char *
  3. 指向浮点型的指针:float *
  4. 指向双精度浮点型的指针:double *
  5. 指向结构体的指针:struct_name *
  6. 指向联合体的指针:union_name *
  7. 指向枚举类型的指针:enum_name *
  8. 指向 void 类型的指针:void *

指针的大小

  1. nt *: 8 字节
  2. char *: 8 字节
  3. float *:8 字节
  4. double *: 8 字节
  5. struct_name *: 8 字节(取决于结构体的大小)
  6. union_name *: 8 字节(取决于联合体的大小)
  7. enum_name *: 8 字节(取决于枚举类型的大小)
  8. void *:8 字节

不同类型指针的移动

不同类型的指针在移动一个单位的大小时,所需要增加或减少的字节数是不同的,它们的大小由它们指向的数据类型决定。以下是一些常见指针类型移动一个单位的大小所需增加或减少的字节数:

  1. int *:4 字节
  2. char *:1 字节
  3. float *:4 字节
  4. double *:8 字节
  5. struct_name *:结构体大小(取决于结构体成员的类型和对齐方式)
  6. union_name *:联合体大小(取决于联合体成员的类型和对齐方式)
  7. enum_name *:4 字节
  8. void *:1 字节

需要注意的是,结构体和联合体的大小取决于其成员的大小和对齐方式,因此在移动这些指针时,需要根据实际情况进行计算。

什么是指针的移动

例如我规定一个数组

int arr[10]={1,2,3,4,5,6,7,8,9,10};

各位学过指针初阶的肯定都知道数组的地址是首元素的地址,而一维数组的的首元素是一个数,在所以我们直接用

int *ptr=arr;

就能得到数组的地址(即首元素地址),此时解引用输出指针我们就数组数组首元素的大小,但是我们如果想让指针指向数组的第二个元素,直接让ptr向后移动一个单位长度(大小为4上面提到过)。

int 的大小为四个字节,也就是说数组每个元素大小都是四个字节,并且int *移动一个大小为4个字节,那么ptr=ptr+1,我们就能得到指向第二个数组元素的指针。

在这个过程中ptr+1就是指针的移动。

数组指针和指针数组的区别

数组指针和指针数组是两个不同的概念。它们在声明、使用和语义上都有所区别。

  1. 数组指针(Pointer to Array):

    • 声明形式:type (*ptr)[size]
    • 它是一个指针,指向一个具有固定大小和数据类型的数组。
    • 指针指向整个数组,可以用于访问数组中的元素。
    • 通过递增指针的方式,可以遍历整个数组。
    • 示例:int (*ptr)[5]; 表示一个指向包含 5 个整数的数组的指针。
  2. 指针数组(Array of Pointers):

    • 声明形式:type *ptr[size]
    • 它是一个数组,其中每个元素都是一个指针。
    • 每个指针可以指向不同类型或大小的数据。
    • 指针数组的每个元素可以分别赋值和访问。
    • 示例:int *ptr[5]; 表示一个具有 5 个整型指针元素的数组。

总结起来,数组指针是指针,指向一个数组;而指针数组是数组,其中的每个元素都是指针。在使用时要注意它们的区别,以确保正确地操作和访问数据。

例如int *(arr[10])[5];

其代表10个数组且每个数组有5个元素

void*类型的指针

void*类型的指针可以接受任何类型的指针,但是其无法解引用。

那么 void* 类型的指针到底有什么⽤呢? ⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以 实现泛型编程的效果。

指针运算

指针的基本运算有三种

分别是: • 指针+- 整数 

                指针-指针 

                指针的关系运算

二级指针

指针变量也是变量,那么用什么来储存指针呢?

这里就要用到二级指针了。

其通常用到函数中接受一级指针的地址

指针数组模拟⼆维数组

#include <stdio.h>
int main()
{
 int arr1[] = {1,2,3,4,5};
 int arr2[] = {2,3,4,5,6};
 int arr3[] = {3,4,5,6,7};
 //数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
 int* parr[3] = {arr1, arr2, arr3};
 int i = 0;
 int j = 0;
 for(i=0; i<3; i++)
 {
 for(j=0; j<5; j++)
 {
 printf("%d ", parr[i][j]);
 }
 printf("\n");
 }

         函数指针

其形式为:int (*)(int x, int y) 

int (*pf3) (int x, int y)
 | | ------------ 
 | | |
 | | pf3指向函数的参数类型和个数的交代
 | 函数指针变量名
 pf3指向函数的返回类型
void test()
{
 printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;
int Add(int x, int y)
{
 return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的

指针的基本已经介绍完毕

  • 27
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

矢鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值