当前位置:网站首页>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;
}边栏推荐
- C language output string in reverse order
- In addition to "adding machines", in fact, your micro service can be optimized like this
- Stylelint check error: unexpected missing generic font family font family no missing generic family keyword
- Fast Planner - detailed explanation of kinetic astar
- 知网、万方数据库免费下载论文------比连接学校内网速度快数倍不止(有的学校万方数据库不支持下载)
- Opencv (I) -- basic knowledge of image
- Implementation of filler creator material editing tool
- Is low code the future of development? On low code platform
- Life game, universe 25 and striver
- CDQ divide and conquer and whole dichotomy learning notes
猜你喜欢
The difference between MVC and MVP and MVVM

知网、万方数据库免费下载论文------比连接学校内网速度快数倍不止(有的学校万方数据库不支持下载)

使用百度飞桨EasyDL实现电商UGC图片自动分类

牛客题目——判断是不是完全二叉树、平衡二叉树

Snowflake ID (go Implementation)

The 21st - -- the 30th time

ShardingSphere-proxy-5.0.0分布式雪花ID生成(三)

Life game, universe 25 and striver

Great Cells & Counting Grids

【pytorch】|transforms.FiveCrop
随机推荐
Clear understanding of torchvision (mind map)
Gurobi——GRBEnv
C语言之程序环境和预处理
CCF-201312-1
Scala branch control (single branch, double branch, multi branch), return value of branch judgment
从零开始Blazor Server(1)--项目搭建
什么是jsp?
HowNet and Wanfang database download papers for free ----- several times faster than connecting to the school intranet (some schools Wanfang database does not support downloading)
Gurobi——GRBModel
低代码是开发的未来吗?浅谈低代码平台
ROS - error in running.Py file in the project
Rotate string left
log4j.jar和slf4-log4下载链接
Cubemx combined with IAR engineering transplantation
Unable to enter the function definition after transferring the IAR project folder to the directory
If you don't want to step on those holes in SaaS, you must first understand the "SaaS architecture"
JDBC连接数据库
Stylelint check error: unexpected missing generic font family font family no missing generic family keyword
Embedded interview
201403-1