当前位置:网站首页>C指针进阶1-->字符指针,数组指针,指针与数组传参,函数指针
C指针进阶1-->字符指针,数组指针,指针与数组传参,函数指针
2022-06-29 22:48:00 【real Wangyanbin】
字符指针
我们在C语言指针部分学习到了指针就相当于是一个地址,指针变量就是存放地址的变量,指针变量的类型就决定着对指针操作时指针操作的精度。±操作指针跳过的大小与指针的类型有着密切的关系,所以什么类型的指针变量就存储什么类型的地址(就是该地址中存储数据的数据类型)。我们口头说的指针就是指针变量。
字符指针顾名思义他就是存储字符类型所在空间的地址,是指向字符类型的指针。字符指针所存储的地址主要有两种不同的形式,
char ch = ‘W’;
char * pc = &ch;
//此种情况就是最为直接的一种—>存放一个字符变量的地址char *pc = “abcdef”;
//存放字符串常量的首地址,相当于—>存放字符串常量
字符指针存放字符串常量的时候,是不是和字符数组很像:
- 字符数组名等价于数组首元素的地址,字符指针变量名存放的是字符串的首地址。
- 字符指针和字符数组名都可以用[]来遍历。
但是他们是有差异的,主要有两点:
字符数组中的数组元素可以改变,但是字符指针所指向的字符串常量是不能改变的,因为字符串常量是一个常量,常量值不能改变。但是字符指针所存储的字符串常量是可以变换的。
int arr[] = “abcdef”
int *pc = “abcdef”;
arr[2]=‘F’;//YES
pc[2] = ‘F’;//ERROR
arr = “ABCDEF”;//ERROR
pc = “ABCDEF”;//YES字符指针存储的是字符串常量的地址,多个不同的字符指针所存储的相同的字符串常量所存储的地址相同。字符数组是存储字符串的,存储相同的字符串的不同的字符数组首元素的地址是不同的
看一个例题:#include<stdio.h> int main() { const char* p1 = "abcdef"; const char* p2 = "abcdef"; char arr1[] = "abcdef"; char arr2[] = "abcdef"; if (p1 == p2) printf("p1==p2\n"); else printf("p1!=p2\n"); if (arr1 == arr2) printf("arr1 == arr2\n"); else printf("arr1 !=arr2\n"); return 0; }上述例题最终结果:
p1==p2
arr1 != arr2
数组指针
数组名与数组指针
我们在C语言指针部分学习了指针数组(详情请看C语言指针初阶),指针数组是指针修饰数组,是一个存放指针类型的数组。数组指针是数组修饰的是指针,这种数据类型就是属于指针,是指针变量中存放的是数组类型的地址。这个数组类型的地址是什么意思,我们先来回忆一下数组名。
数组名是数组首元素的地址,但是有两种情况特殊
- sizeof(数组名);
- &数组名
上述两种数组名代表整个数组的地址,&数组名 取出来的地址是整个数组的地址,数组指针就是指向数组类型的指针,所以数组指针所存储的就是 &数组名
数组指针的格式: int (*pc)[10] ;
- //pc先和结合,说明pc是一个指针变量,然后指针指向的是一个大小为10个整型的数组。所以pc是一个指针,指向一个数组,叫数组指针。数据类型为 int ()[10];
- 特别注意要和:int *p[10];做区分,p先与[]结合,说明p是一个数组,数组中的元素类型是int * 。p的数据类型为 int *[10];
数组指针的应用
1.用数组指针遍历数组
#include<stdio.h>
int main()
{
int arr[] = {
1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", *(*p + i));
}
return 0;
}
- p是指向数组的,*p其实就相当于数组名,数组名又是数组首元素的地址
所以*p本质上是数组首元素的地址
但是这种遍历看着比较复杂,直接用整形指针和数组名遍历不是更加方便吗?
其是数组指针是可以这样用,但不是主要的用途,数组指针主要还是用来函数的传参。
2.用数组指针作为形参接收二维数组
#include<stdio.h>
void print(int(*p)[5], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("%d ", p[i][j]);//*((p+i)+j)<==>p[i][j]
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
print(arr,3,5);
return 0;
}
二维数组名arr代表二维数组首元素的地址,二维数组首元素就是二维数组的第一行相当于一个一维数组的地址,所以可以用数组指针接收。
数组指针概念练习
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
前三行可以很容易的看出来是 数组 指针数组 数组指针。
主要是第四行的,parr3[10]可以看出他是一个数组 去掉parr3[10]得到的int (*)[5]是该数组的元素类型。所以该代码的意思是一个有10个int (*)[5]元素类型的数组,也可以说是存放数组指针的数组。
数组参数、指针参数
在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?
一维数组传参
#include <stdio.h>
void test(int arr[])//ok?
{
}
void test(int arr[10])//ok?
{
}
void test(int* arr)//ok?
{
}
void test2(int* arr[20])//ok?
{
}
void test2(int** arr)//ok?
{
}
int main()
{
int arr[10] = {
0 };
int* arr2[20] = {
0 };
test(arr);
test2(arr2);
}
上述几个函数形参是正确的能顺利接受实参。
二维数组传参
void test(int arr[3][5])//1.ok?
{
}
void test(int arr[][])//2.ok?
{
}
void test(int arr[][5])//3.ok?
{
}
void test(int* arr)//4.ok?
{
}
void test(int* arr[5])//5.ok?
{
}
void test(int(*arr)[5])//6.ok?
{
}
void test(int** arr)//7.ok?
{
}
int main()
{
int arr[3][5] = {
0 };
test(arr);
}
二维数组传参,函数形参的设计只能省略第一个[]的数字。
因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。这样才方便运算。
所以函数1,3形参正确,2形参错误
二维数组名代表二维数组首元素的地址,也就是第一行数组的地址,相当于一个数组名,应该用数组指针来进行接收,4.整形指针错误,5.指针数组错误,6数组指针正确。
对于第七个传参问题,有的同学以为二级指针嘛不就是地址的地址嘛,其实是不正确的,二维数组是存放一级指针变量的地址,而二维数组名是一维数组的地址,所以是错误的。
一级指针传参
如果函数的形参是一级指针,那么可以给函数传参的实参是:数组名,一级指针,变量取地址,以及二级指针解引用(少用);
void print(int* p)
{
}
int main()
{
int a = 10;
int arr[] = {
1,2,3,4,5,6,7,8,9,10 };
int *pa = &a;
int** ppa = &pa;
print(pa);
print(arr);
print(&a);
print(*ppa);
return 0;
}
二级指针传参
二级指针传参一般有三种情况:二级指针,一级指针取地址,指针数组名;
指针数组数组名代表首元素的地址,首元素是指针,所以指针数组名是二级指针
void test(int** p)
{
}
int main()
{
int a = 0;
int* pa = &a;
int** ppa = &pa;
int* parr[10];
test(ppa);
test(&pa);
test(parr);
return 0;
}
函数指针
前面的数组指针,二级指针等都是指向各种类型的数据,但是C语言指针并不是只能指向各种数据,也能指向函数。函数也占据内存空间,其中函数名可以作为函数所占用空间的首地址,&函数名代表是函数所在空间的首地址。
#include<stdio.h>
void test()
{
printf("hello world");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
数组指针是指向数组的指针,整形指针是指向整形的指针,由此推断函数指针是指向函数的指针。
函数指针形式:void (*pfun1)();
其中有很容易混淆的:void *pfun2(); ()的结合性要比*强,所以该代码的意思就是声明一个返回值为void *的函数。
两个有趣的代码
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
代码1:是一个函数调用,是调用0为地址的函数
- 把0强制类型转化为void (*)()–>无参返回类型为void的函数的地址
- 调用0地址处的函数
代码2:
signal是函数名,以上代码是一次函数声明。
声明的signal函数第一个参数类型是int,第二个参数类型是函数指针,该函数指针指向的函数参数是int,返回类型是void,signal函数的返回类型也是一个函数指针,该函数指针指向函数的参数是int,返回类型是void。
代码2太复杂,简化:
typedef unsigned int uint;
typedef void(* pf_t)(int) ;//把void(*)(int)类型重命名为pf_t
边栏推荐
- 80-Redis详解
- [php8+oracle11g+windows environment without tools] Intranet / no network /win10/php connecting to Oracle database instance
- Kr-gcn: an interpretable recommendation system based on knowledge aware reasoning
- R & D test time ratio, bug data analysis
- Design of Distributed Message Oriented Middleware
- Evolution from stand-alone to distributed database storage system
- Status acquisition and control system of on-site express cabinet
- Gnawing down the big bone - sorting (I)
- Daily mathematics serial 54: February 23
- SYSTEMd debugging
猜你喜欢

Optional类的高级使用

Wechat applet: picture seconds plus watermark generation

触摸按键与按键控制对应的LED状态翻转

Node data collection and remote flooding transmission of label information

Code sharing for making and developing small programs on the dating platform

Go zero micro Service Practice Series (VII. How to optimize such a high demand)

VS无法定位程序输入点于动态链接库

With the rise of China's database, Alibaba cloud lifeifei: China's cloud database has taken the lead in various mainstream technological innovations abroad

Digital tracking analysis of insurance services in the first quarter of 2022

Gnawing down the big bone - sorting (I)
随机推荐
wirehark数据分析与取证infiltration.pacapng
math_ Basic elementary function graph (power function / exponent / logarithm / trigonometry / inverse trigonometry)
PhpSpreadsheet读写Excel文件
Processing of error b6267342 reported by AIX small machine in production environment
Phpspreadsheet reading and writing Excel files
Evolution from stand-alone to distributed database storage system
利用kubernetes中的leader选举机制来完成自己的HA应用
Code sharing for making and developing small programs on the dating platform
Kr-gcn: an interpretable recommendation system based on knowledge aware reasoning
Grep tool
从零实现深度学习框架——RNN从理论到实战【实战】
js函数相关的复习
写论文工具:LaTex在线网站
Free PDF to word software sharing, these software must know!
How tcpdump filters specific TCP flag bits
PROJECT #1 - BUFFER POOL [CMU 15-445645]笔记
Wireshark data analysis and forensics information pacapng
nrm详解
Use the leader election mechanism in kubernetes to complete your own ha application
剑指 Offer 38. 字符串的排列