当前位置:网站首页>C语言之指针进阶
C语言之指针进阶
2022-07-27 14:54:00 【小白菜00】
目录
指针初阶

字符指针
char* 一般使用
#include <stdio.h>
void main() {
char* ps = "hello bit";//本质上把字符串首字符的地址存入ps指针
char arr[] = "hello bit";//本质上把字符串放入数组arr里,但是arr数组名表示首元素地址
printf("%c\n", *ps);//h
printf("%c\n", *arr);//h
//给起始位置的地址就可以打印出来,因为以字符串形式打印,所以会从后面找“\0”
printf("%s\n", arr);
printf("%s\n", ps);
}#include <stdio.h>
void main() {
char str1[] = "hello bit";//数组1
char str2[] = "hello bit";//数组2
*str1 = 'p';
printf("%s\n", str1);//可以更改
//下面的字符串为常量字符串在内存中仅存一份并且不可被更改
char* str3 = "hello bit";
char* str4 = "hello bit";
//*str3 = 'p';
//printf("%s\n", str3);//不可更改
printf("%p\n", str1);//0019F88C
printf("%p\n", str2);//0019F878
//下面地址与上面两个地址各不相同,独立出一个空间,为常量字符串地址
printf("%p\n", str3);//00257B30
printf("%p\n", str4);//00257B30
}指针数组
定义:存放指针的数组

#include <stdio.h>
void main() {
int a = 10, b = 20, c = 30;
int* arr1[3] = { &a,&b,&c };//存放整形指针的数组
int i = 0;
for (i = 0; i < 3; i++) {
printf("%d\n", *(arr1[i]));//*(arr1[i])也可以写成*(*(arr1+i))
}
}#include <stdio.h>
void main() {
int a[] = { 1,2,3,4,5 };
int b[] = { 2,3,4,5,6 };
int c[] = { 3,4,5,6,7 };
int* arr[] = {a,b,c};
int i = 0;
for (i = 0; i < 3; i++) {
int j = 0;
for (j = 0; j < 5; j++) {
printf("%d ", *(arr[i] + j));//*(arr[i] + j)也可以写成arr[i][j]
}
printf("\n");
}
}arr[i]等价于:*(arr+i)
数组指针
整形指针:指向整形的指针
字符指针:指向字符的指针
数组指针:指向数组的指针

#include <stdio.h>
void main() {
int arr[] = { 1,2,3,4,5 };
//arr:数组首元素的地址——arr[0]的地址
//&arr:整个数组的地址
int(*parr)[10] = &arr;//parr就是一个数组指针,存放的是数组的地址
double* d[5];//指针数组
double* (*p)[5] = &d;//指针数组的数组指针
}&数组名和数组名
#include <stdio.h>
void main() {
int arr[10] = { 0 };
int* p1 = arr;
int (*p2)[10] = &arr;
printf("%p\n", arr);
printf("%p\n", &arr);
printf("%p\n", arr+1);//地址比上面多4字节
printf("%p\n", &arr+1);//地址比上面多40字节
//由此观之,数组地址的步长为数组首元素地址步长的元素个数倍
}#include <stdio.h>
void main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int(*p)[10] = &arr;
int i = 0;
for (i = 0; i < 10; i++) {
printf("%d ", *((*p) + i));//p是整个数组的地址,*p代表arr
}
}注意:数组名表示首元素的地址,二维数组的首元素是第一行,也就是第一行一维数组的地址也就是一位数组的指针
#include <stdio.h>
print(int(*p)[5], int r, int c) {
int i = 0, j = 0;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("%d ", *(*(p + i) + j));
//p+i——i+1行数组的地址,*(p+i)——i+1行的数组,*(p+i)+j——i+1行数组第j+1行元素的地址,*(*(p + i) + j)——i+1行数组第j+1行元素
}
printf("\n");
}
}
void main() {
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print(arr, 3, 5);
}关于数组代码含义
int arr[5];//整形数组5个元素,每个元素是int
int* p1[10];//指针数组里面可存10个int类型的指针
int(*p2)[10];//int类型10个元素数组的指针
int(*p3[10])[5];//存放数组指针(该指针指向int类型5个元素的数组)的数组(该数组能存10个数组指针)数组参数与指针参数
一维数组传参

1.传过来一个10个元素的整形数组,用自动长度整形数组接受——ok
2.传过来一个10个元素的整形数组,用10个元素的整形数组接受——ok
3.传过来一个数组名(int类型首元素地址)用int类型指针接受——ok
4.传过来一个整形指针的数组可容纳20元素,用20元素整形指针数组接受——ok
5.传过来一个数组名(int*类型首元素地址),用整形二级指针接受——ok
二维数组传参

关于前3个由下面注释可知1,3都ok
4.二维数组传参,其数组名表示首元素的地址也就是第一行一维数组的地址,由此观之,只有6ok
注意:只有双重地址才可用二级指针接受,接受时你还得看类型对不对 。
一级指针传参
#include <stdio.h>
void print(int* p,int sz) {
int i = 0;
for (i = 0; i < sz; i++) {
printf("%d ", *(p + i));
}
}
void main() {
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr1;
int sz = sizeof(arr1) / sizeof(arr1[0]);
print(p, sz);
}二级指针传参
#include <stdio.h>
void test(int** p) {
**p = 20;
}
void main() {
int a = 10;
int* pa = &a;
int** ppa = &pa;
test(ppa);
int b = 7;
int* arr[10] = { &b };
test(arr);
printf("%d\n", a);
printf("%d\n", *(arr[0]));
}函数指针
定义:指向函数的指针(存放函数地址的指针)
#include <stdio.h>
int Add(int a,int b) {
return a + b;
}
void main() {
//&函数名——取到函数的地址
printf("%p\n", &Add);//由此观之,可以得到函数的地址
//注意:数组名!=&数组名,但是函数名==&函数名(函数没首元素的地址)
printf("%p\n", Add);
//函数指针的保存
int (*p1)(int, int) = &Add;//当然,因为函数名==&函数名,所以这里面的&可省略
printf("%p\n", p1);
int (*p2)(int, int) = Add;
printf("%p\n", p2);
//函数的调用
int ret=(*p1)(3, 5);
int res=p2(3, 5);//直接拿函数名调用——p2==&Add而&Add==Add所以p2==Add
printf("%d\n",ret);
printf("%d\n",res);
}函数指针类型:返回值类型 (*)(参数类型列表)
代码阅读

函数指针类型为返回值的声明
void (* signal(int,void(*)(int)))(int);
替代——
void(*)(int) signal(int,void(*)(int));
//简便写法
typedef void(*pfun_t)(int);//对void(*)(int)的函数指针类型重命名为pfun_t;
pfun_t signal(int, pfun_t);函数指针数组
定义:存放函数指针的数组
#include <stdio.h>
int Add(int a,int b) {
return a + b;
}
int Sub(int a, int b) {
return a - b;
}
void main() {
int (*p1)(int, int) = Add;
int (*p2)(int, int) = Sub;
int (*parr[2])(int, int) = {p1,p2};//函数指针数组可存放2个返回值为int参数列表2个int的函数指针
int ret = (*parr[1])(8, 5);//通过函数指针数组进行函数调用1
int res = parr[0](8, 5);//通过函数指针数组进行函数调用2
printf("%d\n", ret);
printf("%d\n", res);
}指向函数指针数组的指针
定义:取出函数指针数组的地址
int arr1[5];//整形数组
int (*p1)[5]=&arr1;//整形数组的指针
int* arr2[5];//整形指针的数组
int* (*p2)[5] = &arr2;//整形指针数组的指针
int (*p3)(int,int);//函数指针
int (*p4[5])(int, int);//函数指针的数组
int (*(*p4)[5])(int, int);//函数指针数组的指针回调函数
定义:

举例:b函数里面有a函数的指针作为参数,当通过a函数的指针反过来调用a函数,这种机制叫回调函数机制,通过指针反过来调用的这个函数叫回调函数。
#include <stdio.h>
int Add(int a,int b) {
return a + b;
}
int AP(int(*p)(int,int)) {
return p(2, 3);//这里我直接省略了*
}
void main() {
int(*ap)(int(*)(int, int)) = &AP;
int ret=ap(&Add);
printf("%d\n", ret);
return;
}#include <stdio.h>
int Add(int a,int b) {
return a + b;
}
int AP(int(*p)(int,int)) {
return p(2, 3);//这里我直接省略了*
}
void main() {
//写法2——反正&AP==ap==AP==*ap所以将*ap用AP取代
int ret=AP(&Add);
printf("%d\n", ret);
return;
}边栏推荐
- android中的图片三级缓存
- 获取当前时间的前N天和前后天的数组列表循环遍历每一天
- Segment tree beats~
- MQ Series 2: technology selection of Message Oriented Middleware
- ShardingSphere-proxy-5.0.0分布式雪花ID生成(三)
- Product axure9 English version, using repeater repeater to realize drop-down multi selection box
- 什么是jsp?
- Random number formula random
- 牛客题目——最小的K个数
- As changes the background theme and background picture
猜你喜欢

kubesphere多节点安装出错

字节跳动服务网格基于 Hertz 框架的落地实践

Rotate the whole model in ADAMS

Exe program encryption lock
mvc和mvp和mvvm的区别

Replication of complex linked list

As changes the background theme and background picture

Filament Creator材质编辑工具的实现

Scala branch control (single branch, double branch, multi branch), return value of branch judgment

jsp-El表达式,JSTL标签
随机推荐
Collection! 0 basic open source data visualization platform flyfish large screen development guide
Servlet用Cookie实现用户上次登录时间
Gurobi——GRBEnv
字符流读取文件
ShardingSphere-proxy-5.0.0分布式雪花ID生成(三)
牛客题目——最小的K个数
[cqoi2012] local minima & Mike and foam
Apache
2021 national vocational college skills competition (secondary vocational group) network security competition questions (9) ideas
Opencv (I) -- basic knowledge of image
Interpretation of C basic syntax: summarize some commonly used but easily confused functions (i++ and ++i) in the program (bit field)
Opencv (II) -- basic image processing
Jerry's built-in touch parameters for modification [chapter]
除了「加机器」,其实你的微服务还能这样优化
UML图介绍
Start from scratch blazor server (1) -- project construction
Process control statement
Cubemx combined with IAR engineering transplantation
Jerry's maximum volume prompt sound cannot be broadcast [article]
LOJ 510 - "libreoj noi round 1" memories outside the north school gate [line segment tree]