- 字符指针
- 数组指针
- 指针数组
- 数组传参和指针传参
- 函数指针
- 函数指针数组
- 指向函数指针数组的指针
- 回调函数
- 指针和数组面试题解析
-
字符指针
- 在指针的类型中有一种指针类型为字符指针 char*
- 一般使用
char* p="abcde"; //常量字符串,不能被改
//p存放的是字符串的起始地址
准确写法是加const修饰
const char* p="abcde";
面试题:
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
const char* p1 = "abcdef";
const char* p2 = "abcdef"; //p1,p2存的是同一个地址
if (arr1 == arr2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
if (p1 == p2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
return 0;
}
-
数组指针
- 是指针,能够指向数组的指针,用来存放数组的地址 int(*p)[N]=&arr; *p==arr
-
char* parr[5]; char* (*pa)[5] = &parr;
-
基本用法;
-
#include <stdio.h> //参数是数组 void print1(int arr[3][5],int x,int y) { int i = 0; int j = 0; for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } //参数是指针 void print2(int(*p)[5], int x, int y) { int i = 0; for (i = 0; i < x; i++) { int j = 0; for (j = 0; j < y; j++) { //arr[i] == *(arr+i) == *(p+i) == p[i] //*(p+i) == p[i] *(p[i]+j) == p[i][j] printf("%d ", *(*(p + 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);//arr数组名 首元素地址 第一行的地址 print2(arr, 3, 5); return 0; }
-
-
指针数组
- 是数组,用来存放指针的数组
-
#include <stdio.h> int main() { int i = 0; int j = 0; int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; int* arr[] = { arr1,arr2,arr3 }; for (i = 0; i < 3; i++) { for (j = 0; j < 5; j++) { printf("%d\t", *(arr[i] + j)); } printf("\n"); } return 0; }
-
数组传参和指针传参
- 一维数组传参可以用数组或指针,数组大小可以省略
- void test( int arr[ ] ) void test( int* arr )
- 二维数组传参可以用二维数组或数组指针,数组的行可以省略,列不可以省略
- void test( int arr[ ][ N ] ) void test( int (*arr)[ 5 ])
- 一级指针传参用一级指针
-
int a = 10; int* p = &a; test(p); void test(int* p) { }
-
- 二级指针或一级指针数组传参用二级指针
-
int n = 10; int* p = &n; int** pp = &p; test(pp); test(&p); int* arr[10]; test(arr); void test(int** ptr) { }
- 一维数组传参可以用数组或指针,数组大小可以省略
-
函数指针
- 是指向函数的指针,存放函数的地址 //&函数名 和 函数名 都是函数的地址
- 定义:返回类型 (*p)(参数类型) p就是函数指针
-
#include <stdio.h> int add(int x,int y) { int z = x + y; return z; } int main() { int (*pa)(int, int) = add; //两种都可以 printf("%d\n", (pa)(2, 3)); printf("%d\n", (*pa)(2, 3));//*没什么作用 return 0; }
-
//代码1 //void (*)() 0 把0强制类型转换成 void(*)() 函数指针类型,0就是一个函数地址 //调用0地址该处的函数 (* (void (*)())0 )(); //代码2 //signal是一个函数声明 //signal返回类型是一个函数指针 void (* signal(int,void(*)(int)) )(int); typedef void(* pfun_t)(int); pfun_t signal(int,pfun_t); typedef unsigned int uint;
《C陷阱和缺陷》
-
函数指针数组
- 存放函数指针的数组
-
用途:转移表
-
#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"); } int main() { int input = 0; int x = 0; int y = 0; //pfarr 是一个函数指针数组——————转移表 int (*pfarr[5])(int, int) = {0, add,sub,mul,div }; do { menu(); printf("请选择模式:\n"); scanf_s("%d", &input); if (input >= 1 && input <= 4) { printf("请输入两个操作数:\n"); scanf_s("%d%d", &x, &y); int ret = pfarr[input](x, y); printf("结果是:%d\n", ret); } else if (input == 0) { printf("退出.......\n"); } else { printf("输入错误,请重新选择:\n"); } } while (input); }
-
- 存放函数指针的数组
-
指向函数指针数组的指针
- 指向函数指针数组的指针是一个指针,指针指向一个数组,数组元素都是函数指针
-
int arr[10] = { 0 }; //指针数组 int (*p)[10] = &arr; //函数指针的数组 int(*parr[10])(int, int); //pparr是一个数组指针,指针指向的数组有10个元素,元素类型是函数指针 int(*(*pparr)[10])(int, int) = &parr;
-
回调函数
- 回调函数就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数,回调函数不是由该函数直接调用,而是在特定的事件或条件发生时由另外一方调用,用于对该事件条件的响应
-
#include <stdio.h> //回调函数 void print(char* str) { printf("hehe:%s\n", str); } void test(void (*p)(char*)) { printf("test\n"); p("bit"); } int main() { test(print); return 0; }
void * 类型的指针不能进行解引用操作
-
-
指针和数组面试题解析