C语言指针高级篇

2023年2月7日11:58:44

相信很多人都听过指针是c语言的灵魂!

      对于指针的学习,往往也是最难的,也是最难搞懂的,那么今天我们一起来学习分析c语言的指针,体会c语言的魅力!

指针和指针应用大概分为一下几类:
1、字符指针
2、数组指针
3、指针数组
4、数组传参和指针传参
5、函数指针
6、函数指针数组
7、指向函数指针数组的指针

这里我就不列举常见数据类型的指针(如:整形类型的指针int * 双精度类型的指针double *等等), 讲字符指针我会连带说下他们。

一、字符指针

字符指针它的功能有:
      1、指向字符串常量(char *str = “abdefg”)
      2、指向字符数组(有一个字符数组char str1[20] = {0}; char str = str1;)
      3、当字符数组作为实参数传递时,形参实际上是字符指针。

(1)在这里,我要提一下第1个功能, 当指向字符串常量时,是不能修改字符串里面的值的,因为常量无法修改,你可以访问它,但不可以修改。
(2)字符串不同于字符,他后面是有结束符’\0’的,千万不能忽略!

接下来请大家做一道习题考察下自己的能力吧!

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	char str1[20] = "wozhenshuai";
	char *str2 = "wozhenshuai";
	printf("%d, %d\n", sizeof(str1), strlen(str1));
	printf("%d, %d\n", sizeof(str2), strlen(str2));
	system("pause");
	return 0;
}

正确答案是:
20,11
4,11

分析上述案例:
      数组名,他一共有3个含义。
      1、指向数组首元素的地址,
      2、sizeof求数组大小,它默认为指向整个数组,上述一共20个元素,每个元素都是char类型,char占用一个字节,所以一共为20*1 = 20字节。
      3、当对数组名取地址符&默认是对整个数组取地址,因此&str1+1 相当横跨整个数组。

二、数组指针&指针数组

      数组指针和指针数组是比较容易搞混的,区分它们的关键在于重心是谁, 何解? 举几个例子

char (*pa)[20];

提前声明: [] 优先级大于*

上面这个例子, 由于(*pa) 加了括号, *的优先级会比[]高, 所以pa是数组指针,
去掉(*pa), 剩下char [20], 因此,这个数组指针指向的是char [20]的数组,长度为20,元素类型为char。

char *pa[20];

的优先级小于[], 因此pa是指针数组, 去掉pa[20], 剩下char指针, 所以这个指针数组里面的成员是char指针类型。

同样可以看出看出类型后,看内部成员类型可以采用去除法, 这个方法很有效。

接下来我们来做几道例题,巩固下自己,分析一下是什么类型?指向什么?

(1)int *p1[6];
(2)int (*p3)[6];

分析总结:
(1)第一道题先观察优先级,很明显[]大于*,因此这是一个数组,去掉p1[6],剩下int*,因此这是一个存放int*类型的数组,数组里面有6个元素,每个元素都是int *型的。
(2)同样观察优先级,(*p1)大于[],因此这是一个指针,去掉(*p3),剩下int [6], 因此这是一个指向int [6]数组的指针,

三、数组传参和指针传参

      数组作为实参传递,接受的形参其实是指针,指针传参,则用对应的指针接受。

下面我们做来做几道习题,通过习题来讲解传参问题

测试1

#include <stdio.h> 
void print(int *p, int sz) 
{    
	int i = 0;    
	for(i=0; i<sz; i++)   
 	{       
 		printf("%d\n", *(p+i));   
 	} 
} 
int main() 
{   
    int arr[10] = {1,2,3,4,5,6,7,8,9};   
    int *p = arr;    
    int sz = sizeof(arr)/sizeof(arr[0]);
    print(arr, sz);
    return 0;
}

这里arr作为实参传入, 还需要传入数组长度。
为什么呢?这是因为传递的数组名(也就是数组首元素地址),他是用指针接收的,对于数组的长度并不知晓!如果有使用数组长度等条件(如题上遍历数组元素)需要将长度作为参数传递!

使用sizeof(数组名) / sizeof(数组首元素) = 数组长度。 这是一个非常方便、轻巧的方式, 希望大家写的时候用起来!

测试2

#include <stdio.h> 
void test(int** ptr) 
{  
	printf("num = %d\n", **ptr);  
} 
int main() 
{  
	int a[3][4] = {0};
	test(a);	
	return 0;
}

上面的代码对吗? 请各位小伙伴运行下这段代码,看看会出现什么错误。
很明显,实参和形参类型不匹配,二维数组的数据类型不是二级指针,而是数组指针,因此形参写成int (*a)[4]。

四、函数指针

      函数是有地址的,和指针一样。那么有地址,我们对它进行取地址会出现什么呢? 结果是还是它本身,因此函数去地址还是它本身。
如果对函数取地址,我们用什么接收它呢? 对它去取地址会是什么类型呢?

void test() 
{  
	printf("hehe\n");
}  
//下面pfun1和pfun2哪个有能力存放test函数的地址? 
void (*pfun1)(); 
void *pfun2();

1、void (*pfun1)();
2、void *pfun2();

答案是void ( * pfun1)()来接收它的地址。
和数组指针一样看法一样, 可以看出这是一个指针, 去掉( * pfun1)之后, 剩余void (), 这是一个函数类型, 返回值为void类型, 函数参数为空。 (只有带()就是函数类型)。

那么它有什么用呢?我们可以调用函数,传递函数指针,然后解引用函数指针然后调用函数,使用函数内部的功能。虽说可以直接调用,但是函数指针可以构建成函数指针数组,数组里面都是函数指针,我们调用就像使用数组一样方便。而且更加系统化!

五、函数指针数组指针&&函数指针数组

下面就是一些扩展!

void test(const char* str) 
{  
	printf("%s\n", str); 
} 
int main() 
{  
	//函数指针pfun  
	void (*pfun)(const char*) = test;  
	//函数指针的数组pfunArr 
 	void (*pfunArr[5])(const char* str);  
 	pfunArr[0] = test;  
 	//指向函数指针数组pfunArr的指针ppfunArr  
 	void (*(*ppfunArr)[10])(const char*) = &pfunArr;  
 	return 0; 
 }

void (pfunArr[5])(const char str);

void (*pfunArr[5])(const char *str);
首先先找到变量名pfunArr,观察发现它是一个数组,去掉pfunArr[5],
剩下void ( * )(const char *str), 观察发现()里面是 *,是指针数组, 去掉( * ), 剩下void (const char * str), 这是函数类型, 所以是函数指针数组
pfunArr是一个长度为5的数组。
数组里面的元素为函数指针,函数的参数为(const char *str),返回值为void。

void (*(ppfunArr)[10])(const char)

void( * ( * ppfunArr)[10])(const char * );
首先先找到ppfunArr,观察发现它是一个指针,去掉 * ppfunArr, 剩下 void( * [10])(const char * ), ()里面是( * [10]),观察发现它是指针数组,因此它是指向指针数组的指针, 去掉[10], 剩下void ( * )(const char * ), 观察发现它是函数指针, 故这是一个指向函数指针数组的指针,函数的参数为const char*, 返回值为void。

结尾

函数指针数组和函数指针数组指针是对函数指针更好的调用,更加方便地使用函数功能,他的使用和数组指针和指针数组地使用比较相似,就只是解引用后是函数调用而已!大家多多品味就可以了,很好理解的!
好啦,今天就分享到这里了,最近忙着期末考试,随后空闲时候,我会继续分享和大家共同学习,感受c语言的魅力!

ps:
致敬以前写的博客, 当时还不太会写博客, 一些语法不会, 现在修复很多, 这篇博客算是能看啦!加油,自己!!!

  • 作者:GlorygloryGlory
  • 原文链接:https://blog.csdn.net/weixin_44024891/article/details/94051951
    更新时间:2023年2月7日11:58:44 ,共 3446 字。