C语言——指针(进阶)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言——指针(进阶)相关的知识,希望对你有一定的参考价值。
- 字符指针
- 数组指针
- 指针数组
- 数组传参和指针传参
- 函数指针
- 函数指针数组
- 指向函数指针数组的指针
- 回调函数
一:字符指针
指针类型中字符指针 char*
#include<stdio.h>
int main()
char* pa = "good bye";
//printf("%c\\n",*pa);//本质是把字符串的首字符的地址存储在pa中
char* pa = "good bye";
char arr[] = "good bye";
printf("%s\\n",pa);
printf("%s\\n",arr);
return 0;
例题:
#include <stdio.h>
int main()
char str1[] = "game";
char str2[] = "game";
//两个不同数组,新创造的空间不同
const char* str3 = "computer";
const char* str4 = "computer";
//常量字符串是不能改的,只会存一份,所以两个指针变量都指向同一个地址
if (str1 == str2)
printf("str1 and str2 are same\\n");
else
printf("str1 and str2 are not same\\n");
if (str3 == str4)
printf("str3 and str4 are same\\n");
else
printf("str3 and str4 are not same\\n");
return 0;
//str1 and str2 are not same
//str3 and str4 are same
二:数组指针(指向数组的指针)
1.数组指针
#include<stdio.h>
int main()
int a = 10;
int* pa = &a;//整形指针
char b = q;
char* pb = &b;//字符指针
int arr[5] = 1,2,3,4,5;
int (*parr)[5] = &arr;//由于[]的优先级高于*,得带括号
从parr处开始,先与*结合,说明P 是一个指针 然后再与[]结合,说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以parr 是一个指向由整型数据组成的数组的指针
(怎么判断呢? 看变量先与谁结合)
2:&数组名和数组名
差分别为4 ,40。
&arr取的是整个数组的地址,而arr是数组首元素的地址
3:应用
//二维数组
#include<stdio.h>
void print1(int arr[3][5], int m, int n)
int i = 0;
int j = 0;
for (i = 0; i < m; i++)
int j = 0;
for (j = 0; j < n; j++)
printf("%d ", arr[i][j]);
printf("\\n");
//数组指针
void print2(int(*arr)[5], int r, int c)
int i = 0;
for (i = 0; i < r; i++)
int j = 0;
for (j = 0; j < c; j++)
printf("%d ", *(*(arr + i) + j));
printf("\\n");
int main()
int arr[3][5] = 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 ;
print1(arr, 3, 5);
print2(arr, 3, 5);
return 0;
//print1,2
//1 2 3 4 5
//2 3 4 5 6
//3 4 5 6 7
注意:
int(*parr[10])[5];
//首先parr[10]是个数组,去掉parr[10]后为指向的类型
//parr是以个存放数组指针的数组,能存放10个数组指针
//每个数组指针都能指向一个数组,数组有五个元素,均为int类型
三:指针数组(是一个存放指针的数组)
#include<stdio.h>
int main()
//指针数组-数组中存放指针(地址)
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int* arr[5] = &a,&b,&c,&d;
int i = 0;
for (i=0;i<4;i++)
printf(" %d\\n ", *(arr[i]));
#include<stdio.h>
int main()
int a1[] = 1,2,3,4,5 ;
int a2[] = 2,3,4,5,6 ;
int a3[] = 3,4,5,6,7 ;
int* arr[3] = a1,a2,a3 ;//代表各数组首元素的地址
int i = 0;
for (i=0;i<3;i++)//行
int j = 0;
for (j=0;j<5;j++)//列
printf("%d ", *(arr[i] + j));
//可以写成 printf("%d ", arr[i][j]);
printf("\\n");
return 0;
//1 2 3 4 5
//2 3 4 5 6
//3 4 5 6 7
四:数组传参和指针传参
1:一维数组传参
#include <stdio.h>
void test1(int arr[10])//可以
void test1(int arr[])//可以,元素个数可以省略
void test1(int* arr)//可以,指针
void test2(int* arr[20])//可以,存放int* 的整型指针数组
void test2(int** arr)//可以,二级指针
int main()
int arr1[10] = 0;
int* arr2[10] = 0;//存放int*的数组
test1(arr1);
test2(arr2); //指向int* 的首元素地址
2:二维数组传参
实参 只用填数组名 就行
形参可以为 二维数组 或 指针
//二维数组
void test(int arr[3][5])//可以
void test(int arr[][])//错误。行可省略,列是不能省的
void test(int arr[][5])//可以
//指针
void test(int* arr)//不行。接收第一行的地址,第一行是5个整形的数组,不能用指针接收
void test(int* arr[5])//不行。这是指针数组,得要整型数组指针才行
void test(int(*arr)[5])//可以。为整型数组指针
void test(int** arr)//不行。
int main()
int arr[3][5] = 0 ;
test(arr);
return 0;
3:一级指针传参
#include <stdio.h>
void print(int* pstr, int sz) //用一级指针接收
int i = 0;
for (i = 0; i < sz; i++)
printf("%d ", *(pstr + i));
void test(char* p)
int main()
int arr[7] = 2,0,2,2,10,0,2 ;
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
print(p, sz);//p是一级指针
char ch = a;
test(&ch);//char*类
//char* p1 = &ch;
//test(p1);
return 0;
4:二级指针传参
#include <stdio.h>
void test(int** pstr) //二级指针接收
printf("num = %d\\n", **pstr);//a的值
int main()
int a = 10;
int* pa = &a;//pa是一级指针
int** ppa = &pa;//ppa是二级指针
test(ppa);//二级指针传参
test(&pa);取一级指针的地址就是二级指针
int* arr[10] = 0;
test(arr);//也可以,传存放一级指针的数组
//,传的是整形指针数组的首元素的地址,而首元素为int*类型,结果为二级指针传参
return 0;
五:函数指针(存放函数地址的指针)
&函数名——取出函数的地址
注意:数组名 != &数组名
函数名 == &函数名
int (*pf)(int,int) = &Add;
#include<stdio.h>
int Add(int x,int y)
return x + y;
int main()
printf("%p\\n", Add);
printf("%p\\n", &Add);
//地址相同,意义一样,无区别
int (*pf)(int,int) = &Add;// 函数指针中,由于()优先级高于*,得带括号
int ret = (*pf)(7,5);//通过函数指针调用函数.1
//int ret = pf(7,5);//2
//int ret = Add(7,5);//3
//1,2,3都一样。*的作用不大,可有可无,但只能在函数指针中这样
//int ret = *pf(7,5);//这样是不行的,等于对函数的结果12进行解引用。若加*得括起来
printf("%d\\n",ret);//12
return 0;
例子:
#include<stdio.h>
void test(char* str)
int main()
void (*pt)(char*) = &test;//与函数要对应
return 0;
六:函数指针数组(存放函数指针的数组)
它可以存放多个参数相同,返回类型相同 的函数地址
int (*arr[3])(int, int) = Add,Sub,Mul;
#include<stdio.h>
int Add(int x, int y)//加
return x + y;
int Sub(int x, int y)//减
return x - y;
int Mul(int x, int y)//乘
return x * y;
int main()
//parr就是 函数指针数组
int (*parr[3])(int, int) = Add,Sub,Mul;
return 0;
写一个计算器(加,减,乘,除):
(函数指针数组的用途:转移表)
#include<stdio.h>
int Add(int x, int y)//加
return x + y;
int Sub(int x, int y)//减
return x - y;
int Mul(int x, int y)//乘
return x * y;
int Div(int x, int y)//除
return x / y;
void menu()
printf("********************************\\n");
printf("**** 1.Add 2.Sub ****\\n");
printf("**** 3.Mul 4.Div ****\\n");
printf("**** 0.exit ********\\n");
printf("********************************\\n");
int main()
int input = 0;
do
menu();//菜单
//pfArr是函数指针数组
//转移表
int (*pfArr[5])(int, int) = NULL, Add, Sub, Mul, Div ;//
int x = 0;
int y = 0;
int ret = 0;
printf("请选择:>");
scanf("%d",&input);
if(input>=1 && input<=4)
printf("请输入2个数:>");
scanf("%d %d", &x, &y);
ret = (*pfArr[input])(x, y);
printf("%d\\n",ret);
else if(input == 0)
printf("退出程序\\n");
else
printf("选错了,重新选择");
while(input);
return 0;
,
七:指向函数指针数组的指针
int(*p)(int,int);//函数指针
int(* p2[4])(int,int);//函数指针的数组
int(*(*p3)[4])(int,int);//取出函数指针数组的地址
//p3是一个指向函数指针数组的指针
补充:int arr[5];
数组元素类型:去掉数组名和元素个数 , 剩下的就是——>int
数组类型 :仅去掉数组名 ——>int[5]
八:回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针作为参数传给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
回调函数应用例子:
int Add(int x, int y)
return x + y;
int Sub(int x, int y)
return x - y;
int Mul(int x, int y)
return x * y;
int Div(int x, int y)
return x / y;
void menu()
printf("***************************\\n");
printf("***** 1.add 2. sub ****\\n");
printf("***** 3.mul 4. div ****\\n");
printf("***** 0.exit ****\\n");
printf("***************************\\n");
//回调函数
int Cald(int (*pf)(int, int))
int x = 0;
int y = 0;
printf("请输入2个值:>");
scanf("%d %d", &a, &b);
return pf(x,y);
int main()
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
case 1:
ret = Cald(Add);//把Add函数指针传过去
//Add函数并不是直接调用的,而是通过函数指针调用的
printf("%d\\n", ret);
break;
case 2:
ret = Cald(Sub);//把Sub函数指针传过去
printf("%d\\n", ret);
break;
case 3:
ret = Cald(Mul);//把Mul函数指针传过去
printf("%d\\n", ret);
break;
case 4:
ret = Cald(Div);//把Div函数指针传过去
printf("%d\\n", ret);
break;
case 0:
printf("退出程序\\n");
break;
default:
printf("选错了,重新选择\\n");
break;
while (input);
qsort 库函数(进行快速排序的实现)
(得引用头文件 stdlib.h )
void qsort (void* base,//void*能接收任意类型的地址,应用更加广泛;base中存放的是 待排序的数据里的第一个对象的地址
size_t num,//元素个数
size_t size,//一个元素占几个字节
int (*compar)(const void*,const void*)//用来比较待排序数据中的2个元素的函数
);
//
注意:int compareMyType (const void * a, const void * b)
if ( *(MyType*)a < *(MyType*)b ) return -1;
if ( *(MyType*)a == *(MyType*)b ) return 0;
if ( *(MyType*)a > *(MyType*)b ) return 1;
例子:用qsort函数进行排序
#include<stdio.h>
#include<stdlib.h>
int compar(const void* d1, const void* d2)
return *(int*)d1 - *(int*)d2 ;
void print_arr(int arr[],int sz)
int i = 0;
for(i=0;i<sz;i++)
printf("%d\\n",arr[i]);
printf("\\n");
int main()
int arr[10] = 9,8,7,6,5,4,3,2,1,0 ;
int sz = sizeof(arr)/sizeof(arr[0]);
qsort(arr,sz, sizeof(arr[0]), compar);//排序
print_arr(arr, sz);
return 0;
以后继续补充qsort函数内容
以上是关于C语言——指针(进阶)的主要内容,如果未能解决你的问题,请参考以下文章