回调函数
冒泡回调实现升降序
huidiao.h
#ifndef _HUIDIAO_H
#define _HUIDIAO_H
#include <stdbool.h>
// 升序
extern bool ascend(int a, int b);
// 降序
extern bool descend(int a, int b);
#endif
maopao.h
#ifndef _MAOPAO_H
#define _MAOPAO_H
#include<stdio.h>
#include<stdbool.h>
typedef bool (*CompareFunc)(int, int);// 声明回调函数的类型
void maopao(int *buf,int num, CompareFunc compare);
#endif
huidiao.c
#include "huidiao.h"
// 升序
bool ascend(int a, int b)
{
return (a-b > 0) ? true : false; // > 0
}
// 降序
bool descend(int a, int b)
{
return (a-b < 0) ? true : false; // < 0
}
main.c
#include<stdio.h>
#include"maopao.h"
#include"huidiao.h"
int main(int argc, char const *argv[])
{
int buf[100]={};
int num;
printf("输入冒泡个数:");
scanf("%d",&num);
printf("输入:");
for(int i=0;i<num;i++)
{
scanf("%d",&buf[i]);
}
maopao(buf,num,ascend);//升序
for(int i = 0; i < num; i++)
{
printf("%d\t",buf[i]);
}
printf("\n");
return 0;
}
maopao.c
#include"maopao.h"
#include"huidiao.h"
void maopao(int *buf,int num, CompareFunc compare)
{
for (int i=0;i<num-1;i++)
{
for(int j=0;j<num-i-1;j++)
{
if(compare(buf[j], buf[j+1])) // 调用回调函数进行比较
{
int temp=buf[j];
buf[j]=buf[j+1];
buf[j+1]=temp;
}
}
}
}
内联函数
max.h
#ifndef _MAX_H
#define _MAX_H
#include<stdio.h>
extern int max(int ,int);
#endif
max.c
#include"max.h"
inline int max(int a, int b)
{
return a > b ? a : b;
}
main.c
#include"max.h"
int main(int argc, char const *argv[])
{
int a=20,b=10;
printf("%d",max(a,b));
return 0;
}
递归函数
递归概念:如果一个函数内部,包含了对自身的调用,则该函数称为递归函数。
自己调用自己,注意需要有结束条件,否则会出现内存溢出(段错误)
什么时候用到递归 : 需要满足有规律递减条件,递减到某个程度是可以退出的
func()
{
func()
}
用malloc开辟二维数组
1.使用2级指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int **ptr, int row, int col)
{
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
printf("%d\t",ptr[i][j]);
}
printf("\n");
}
}
int main(int argc, char const *argv[])
{
// 数组[]表示数据的个数,总大小是数据个数*类型
int buf[3];// 3*4
// malloc实参是以字节为单位,相当于一维数组
int *ptr = malloc(3*sizeof(int));
for(int i = 0; i < 3; i++)
{
ptr[i] = i;
}
// 将mallc转为二维数组
// 3行
int **ptr1 = (int **)malloc(3*sizeof(int));
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 4; j++)
{
ptr1[i] = (int *)malloc(4*sizeof(int));
}
}
int count = 0;
int i,j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
ptr1[i][j] = ++count;
}
}
func(ptr1,i,j);
free(ptr1);
ptr1 = NULL;
return 0;
}
2.数组指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int (*ptr)[4], int row, int col)
{
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
printf("%d\t",ptr[i][j]);
}
printf("\n");
}
}
int main(int argc, char const *argv[])
{
// 定义数组指针,每个指针指向4个元素的首地址
int (*p)[4] = (int (*)[4])malloc(3*4*sizeof(int));
int count = 0;
int i,j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
p[i][j] = ++count;
}
}
func(p,i,j);
// for(int i = 0; i < 3; i++)
// {
// for(int j = 0; j < 4; j++)
// {
// printf("%d\t",p[i][j]);
// }
// printf("\n");
// }
return 0;
}
静态数据(面试必考)**
c语言中,静态数据有两种:
- 全局变量:定义在函数外的变量
- 静态局部变量:定义在函数内部,且被static修饰的变量
为什么需要静态数据
- 全局变量在默认的情况下,对所有文件可见,为某些需要在各个不同文件和函数之间访问的数据提供操作上的方便。
- static修饰的全局变量,只能在本文件使用,如果未被static修饰的全局变量,所有的文件都能使用,会出现命名污染。
- 当我们希望一个函数退出后依然能保留局部变量的值,以便于下一次调用时还能用,静态局部变量可以帮助实现这样的功能。
指针运算
- 指针加法意味着地址向上移动若干个目标
- 指针减法意味着地址向下移动若干个目标
示例:
int a = 100;
int *p = &a; // 指针 p 指向整型变量 a
int *k1 = p + 2; // 向上移动 2 个目标(2个int型数据)
int *k2 = p - 3; // 向下移动 3 个目标(3个int型数据)
指针运算
int a = 10;
//int *p = &a;// 初始化
int *p;
// 其它时候用来表示 *单独使用为解引用,所以 *p = &a; 错误
p = &a;
printf("a value:%d\n",a);
printf("*(&a) value:%d\n",*(&a));// * 与 &是互逆运算
printf("%d\n",*p);
*p = 300; //*p 此时相当于变量a
printf("a value:%d\n",a);
指针偏移
指针的加减称为指针的偏移,偏移的单位由指针的类型大小所决定所谓指针的类型大小指的是指针变量所指向的内存空间的数据类型
数组与指针
printf("%ld\n",sizeof(a));
第二个含义,表示首元素地址
int *p = a;
数组下标
int a[3] = {1,2,3};
int b = a[0];
int c1 = *(a+0); // a[0]
int c2 = *(a+1); // a[1]
int c3 = *(a+2); // a[2]
int d1 = *(0+a); // a[0]
int d2 = *(1+a); // a[1]
int d3 = *(2+a); // a[2]
printf("2[a] = %d\n",2[a]); // *(2+a) 仅限面试用
int a[3] = {1,2,3};
printf("%d,%d,%d,%d\n",a[0],*(a+0),*(0+a),0[a]);
// *的作用就是[]相当于解引用
printf("%d,%d,%d,%d\n",a[1],*(a+1),*(1+a),1[a]);
return 0;
总结:数组最后编译器会自动转为指针操作,数组运算其实就是指针运算
指针转数组
int b[10];
// 指针没有让它指向对应的空间,会出现段错误
int *a = b;
a[0] = 1;
printf("%d\n",a[0]);
// 如果是指针操作,会修改原有空间的内容
// 指针与原空间为同一块空间
int a[3] = {3,4,5};
int *p = a;
p[1] = 10;
printf("%d,%d,%d\n",*(p+1),p[1],a[1]);
// 空间不属于同一块空间
int b = 19;
int q = b;
q = 18;
printf("%d,%d\n",b,q);
总结 :
1.指针一定要指向一块合法的空间,否则出现段错误,没有空间自行分配
2.可以将指针转换成数组使用,如上所示