网站开发环境的意义网页设计培训哪好
- 作者: 五速梦信息网
- 时间: 2026年03月21日 07:37
当前位置: 首页 > news >正文
网站开发环境的意义,网页设计培训哪好,wordpress 截取函数,怎么开个网店卖东西文章目录 1.内存和地址1.1内存1.2究竟该如何理解编址 2.指针变量和地址2.1 取地址操作符#xff08;#xff09;2.2指针变量和解引用操作符#xff08;*#xff09;2.2.1指针变量2.2.2如何拆解指针类型2.2.3解引用操作符 2.3 指针变量的大小 3.指针变量类型的意义3.1指… 文章目录 1.内存和地址1.1内存1.2究竟该如何理解编址 2.指针变量和地址2.1 取地址操作符2.2指针变量和解引用操作符2.2.1指针变量2.2.2如何拆解指针类型2.2.3解引用操作符 2.3 指针变量的大小 3.指针变量类型的意义3.1指针的解引用3.2指针-整数3.3 void 指针 4.指针运算4.1指针-整数4.2指针-指针4.3 指针的关系运算 5.const修饰指针5.1 const修饰指针5.2 const 修饰指针变量 6.野指针6.1野指针成因6.1.1指针未初始化6.1.2 指针的越界访问6.1.3指针指向的空间释放 6.2如何规避野指针6.2.1指针初始化6.2.2小心指针越界6.2.3指针变量不再使用时及时置NULL指针使用之前检查有效性6.2.4避免返回局部变量的地址 7.assert断言8.指针的使用和传址调用8.1 strlen的模拟实现8.2传值调用和传址调用 9.数组名的理解10.使用指针访问数组11.一维数组传参的本质12.冒泡排序13.二级指针14.指针数组15.指针数组模拟二维数组16.字符指针变量17.数组指针变量17.1数组指针变量是什么17.2数组指针变量怎么初始化 18.二维数组传参的本质19.函数指针变量19.1函数指针变量的创建19.2函数指针变量的使用19.3两段有趣的代码19.3.1 typedef 关键字 20.函数指针数组21.转移表22.回调函数是什么23.qsort使用举例23.1使用qsort函数排序整形数据23.2使用sqort排序结构数据 24.qsort函数的模拟实现 1.内存和地址
1.1内存
我们知道计算机上CPU中央处理器在处理数据的时候需要的数据是在内存中读取的处理后的数据也会放回内存中那我们买电脑的时候电脑上内存是8GB/16GB/32GB等那这些内存空间如何⾼效的管理呢 其实也是把内存划分为⼀个个的内存单元每个内存单元的⼤⼩取1个字节 ⼀个⽐特位可以存储⼀个2进制的位1或者0 1byte 8bit 1KB 1024byte 1MB 1024KB 1GB 1024MB 1TB 1024GB 1PB 1024TB 1.2究竟该如何理解编址
CPU访问内存中的某个字节空间必须知道这个字节空间在内存的什么位置⽽因为内存中字节很多所以需要给内存进⾏编址
计算机中的编址并不是把每个字节的地址记录下来⽽是通过硬件设计完成的
⾸先必须理解计算机内是有很多的硬件单元⽽硬件单元是要互相协同⼯作的。所谓的协 同⾄少相互之间要能够进⾏数据传递。但是硬件与硬件之间是互相独⽴的那么如何通 信呢答案很简单⽤线连起来。⽽CPU和内存之间也是有⼤量的数据交互的所 以两者必须也⽤线连起来。
我们今天关⼼⼀组线叫做地址总线。
32位机器有32根地址总线每根线只有两态表⽰0,1【电脉冲有⽆】那么⼀根线就能表⽰2种含义2根线就能表⽰4种含义依次类推。32根地址线就能表⽰2^32种含义每⼀种含义都代表⼀个地址。
地址信息被下达给内存在内存上就可以找到该地址对应的数据将数据在通过数据总线传⼊CPU内寄存器
2.指针变量和地址
2.1 取地址操作符
在C语⾔中创建变量其实就是向内存申请空间 上述的代码就是创建了整型变量a内存中申请4个字节⽤于存放整数10其中每个字节都 有地址上图中4个字节的地址分别是 0x006FFD70 0x006FFD71 0x006FFD72 0x006FFD73 2.2指针变量和解引用操作符*
2.2.1指针变量
那我们通过取地址操作符()拿到的地址是⼀个数值⽐如0x006FFD70这个数值有时候也是需要存储起来⽅便后期再使⽤的那我们把这样的地址值存放在哪⾥呢答案是指针变量中 int* pa a; //取出a的地址并存储到指针变量pa中 指针变量也是⼀种变量这种变量就是⽤来存放地址的存放在指针变量中的值都会理解为地址
2.2.2如何拆解指针类型 2.2.3解引用操作符
在现实⽣活中我们使⽤地址要找到⼀个房间在房间⾥可以拿去或者存放物品。 C语⾔中其实也是⼀样的我们只要拿到了地址指针就可以通过地址指针找到地址指针指向的对象这⾥必须学习⼀个操作符叫解引⽤操作符() int a 100;int pa a;*pa 0;*pa的意思就是通过pa中存放的地址找到指向的空间,*pa其实就是a变量了所以 *pa0这个操作符是把a改成了0
2.3 指针变量的大小
前⾯的内容我们了解到32位机器假设有32根地址总线每根地址线出来的电信号转换成数字信号后 是1或者0那我们把32根地址线产⽣的2进制序列当做⼀个地址那么⼀个地址就是32个bit位需要4个字节才能存储
同理64位机器假设有64根地址线⼀个地址就是64个⼆进制位组成的⼆进制序列存储起来就需要 8个字节的空间指针变量的⼤⼩就是8个字节。
3.指针变量类型的意义
3.1指针的解引用 3.2指针±整数
#include stdio.h
int main()
{
int n 10;
char pc (char)n;
int pi n;
printf(%p\n, n);
printf(%p\n, pc);
printf(%p\n, pc1);
printf(%p\n, pi);
printf(%p\n, pi1);
return 0;
}char 类型的指针变量1跳过1个字节这就是指针变量的类型差异带来的变化。 int* 类型的指针变量1跳过了4个字节 结论指针的类型决定了指针向前或者向后⾛⼀步有多⼤距离
3.3 void* 指针
在指针类型中有⼀种特殊的类型是void* 类型的可以理解为⽆具体类型的指针或者叫泛型指 针这种类型的指针可以⽤来接受任意类型地址。但是也有局限性void* 类型的指针不能直接进⾏指针的±整数和解引⽤的运算。 #include stdio.hint main(){int a 10;void* pa a;void* pc a;*pa 10;pc 0;return 0;}那么void 类型的指针到底有什么⽤呢⼀般void* 类型的指针是使用在函数参数的部分⽤来接收同类型数据的地址这样的设计可以实现泛型编程的效果使得⼀个函数来处理多种类型的数据
4.指针运算
4.1指针±整数
#include stdio.h
int main()
{int arr[9] {1, 2, 3, 4, 5, 6, 7, 8, 9};int* p arr[0];int sz sizeof(arr) / sizeof(arr[0]);for (int i 0;i 9;i){printf(%d , (pi));}return 0;
}4.2指针-指针
1.指针-指针时两个指针指向同一块区域 2.指针-指针的绝对值是两个指针之间的元素个数
#include stdio.h
int main()
{ int arr[6] { 1,2,3,4,5,6 };int c arr[5] - arr[0];printf(%d, c);//5return 0;
}库函数strlen实现
#include stdio.h
size_t mystrlen(char str)
{size_t* p str;while (str ! \0)str;return str - p;
}
int main()
{ char arr[] abcdefj;size_t len mystrlen(arr);printf(%zd, len);//7return 0;
}4.3 指针的关系运算
两个地址可以比较大小
数组随着下标增长地址从低到高变化
#include stdio.h
int main()
{ int arr[] { 1,2,3,4,5 };int p arr;int sz sizeof(arr) / sizeof(arr[0]);while (p arr[sz]){printf(%d , *p);p;}return 0;
}5.const修饰指针
5.1 const修饰指针
变量是可以修改的如果把变量的地址交给⼀个指针变量通过指针变量的地址的改变也可以修改这个变量。 但是如果我们希望⼀个变量加上⼀些限制不能被修改怎么做呢这就是const的作⽤ #include stdio.hint main(){int m 0;m 20;//m
是可以修改的
const int n 0;n 20;//n
是不能被修改的
return 0;}但是如果我们绕过n使⽤n的地址去修改n就能做到了虽然这样做是在打破语法规则 #include stdio.h
int main()
{
const int n 0;
printf(n %d\n, n);//0
int*p n;
p 20;
printf(n %d\n, n);//20
return 0;
}我们可以看到这⾥⼀个确实修改了但是我们还是要思考⼀下为什么n要被const修饰呢就是为了 不能被修改如果p拿到n的地址就能修改n这样就打破了const的限制这是不合理的所以应该让 p拿到n的地址也不能修改n那接下来怎么做呢
5.2 const 修饰指针变量
#include stdio.h
int main()
{ int num 10;int m 30;const int p num;//num不能再改变了p m;printf(%d\n, *p);//30return 0;
}const如果放在*的左边修饰的是指针指向的内容保证指针指向的内容不能通过指针来改变。 但是指针变量本⾝的内容可变。 const如果放在*的右边修饰的是指针变量本⾝保证了指针变量的内容不能修改但是指针指 向的内容可以通过指针改变
6.野指针
概念野指针就是指针指向的位置是不可知的随机的、不正确的、没有明确限制的 理解野指针的时候你可以把野指针想成“野狗”是没有主⼈的是危险的
6.1野指针成因
6.1.1指针未初始化
p没有指向空间
#include stdio.hint main(){
int *p;//
局部变量指针未初始化默认为随机值
p 20;return 0;}6.1.2 指针的越界访问
#include stdio.h
int main()
{ int arr[10] { 0 };int p arr;for (int i 0;i 11;i){*(p) 1;}return 0;
}当指针指向的范围超过数组arr时p就是野指针
6.1.3指针指向的空间释放 p得到地址的一瞬间就是野指针了
6.2如何规避野指针
6.2.1指针初始化
如果明确知道指针指向哪⾥就直接赋值地址如果不知道指针应该指向哪可以给指针赋值NULL. NULL 是C语⾔中定义的⼀个标识符常量值是00也是地址这个地址是⽆法使⽤的读写该地址 会报错 #include stdio.hint main(){int num 10;intp1 num;int p2 NULL;return 0;}6.2.2小心指针越界
⼀个程序向内存申请了哪些空间通过指针也就只能访问哪些空间不能超出范围访问超出了就是 越界访问。 使⽤指针的时候⼀定要注意边界通过指针访问的内存是不能越界的 例子如 2.1.2
6.2.3指针变量不再使用时及时置NULL指针使用之前检查有效性
当指针变量指向⼀块区域的时候我们可以通过指针访问该区域后期不再使⽤这个指针访问空间的时候我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是只要是NULL指针就不去访问 同时使⽤指针之前可以判断指针是否为NULL
#include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,10};int p arr[0];for(i0; i10; i){(p) i;}//
此时p已经越界了可以把p置为NULLp NULL;//
下次使⽤的时候判断p不为NULL的时候再使⽤
//…p arr[0];//
重新让p获得地址
if(p ! NULL) //判断
{//…}return 0;}6.2.4避免返回局部变量的地址
如2.1.3 不要返回局部变量的地址。
7.assert断言
assert.h 头⽂件定义了宏assert() ⽤于在运⾏时确保程序符合指定条件如果不符合就报错终⽌运⾏。这个宏常常被称为“断⾔” assert(p ! NULL); //验证p是否等于NULL如果不等于就继续运行否则停止运行并给出报错信息 assert() 宏接受⼀个表达式作为参数。 如果该表达式为真返回值⾮零 assert()不会产⽣任何作⽤程序继续运⾏ 如果该表达式为假返回值为零assert() 就会报错在标准错误流stderr 中写⼊⼀条错误信息显⽰没有通过的表达式以及包含这个表达式的⽂件名和⾏号
8.指针的使用和传址调用
8.1 strlen的模拟实现
#include stdio.h
#include assert.h
size_t my_strlen(const char* str)
{size_t count 0;assert(str ! NULL);while (str ! \0){count;str;}return count;
}
int main()
{char arr[] abcdef;size_t len my_strlen(arr);printf(%zd, len);return 0;
}8.2传值调用和传址调用
在函数调⽤的时候有传值调⽤也有传址调⽤那这两种调⽤⽅式有什么区别呢 传址调⽤就得使⽤指针学习指针的⽬的是使⽤指针解决问题那什么问题⾮指针不可呢
例如写⼀个函数交换两个整型变量的值 ⼀番思考后我们可能写出这样的代码 #include stdio.hvoid Swap1(int x, int y){int tmp x;x y;y tmp;}int main(){int a 0;int b 0;scanf(%d %d, a, b);Swap1(a, b);printf(
交换前
a%d b%d\n, a, b);printf(
交换后
a%d b%d\n, a, b);return 0;}结论实参传递给形参的时候形参会单独创建⼀份临时空间来接收实参对形参的修改不影响实 参。 所以Swap是失败的了
那怎么办呢 我们现在要解决的就是当调⽤Swap函数的时候Swap函数内部操作的就是main函数中的a和b直接 将a和b的值交换了。那么就可以使⽤指针了在main函数中将a和b的地址传递给Swap函数Swap 函数⾥边通过地址间接的操作main函数中的a和b并达到交换的效果就好了
#include stdio.h
void swap(int a1, int* b1)
{int t *a1;*a1 *b1;b1 t;
}
int main()
{ int a 10;int b 0;swap(a, b);printf(%d %d, a, b);return 0;
}这⾥调⽤swap函数的时候是将变量的地址传递给了函数这种函数调⽤⽅式叫传址调⽤
传址调⽤可以让函数和主调函数之间建⽴真正的联系在函数内部可以修改主调函数中的变量所以未来函数中只是需要主调函数中的变量值来实现计算就可以采⽤传值调⽤。如果函数内部要修改主调函数中的变量的值就需要传址调⽤
9.数组名的理解
数组名是⾸元素的地址 #include stdio.hint main(){int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf(arr[0] %p\n, arr[0]);printf(arr %p\n, arr);
return 0;} 数组名如果是数组⾸元素的地址那下⾯的代码怎么理解呢?
#include stdio.h
int main(){int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf(%d\n, sizeof(arr));return 0;}输出的结果是40如果arr是数组⾸元素的地址那输出应该的应该是4/8才对 #include stdio.h
int main()
{
int arr[10] { 1,2,3,4,5,6,7,8,9,10 };
printf(arr[0] %p\n, arr[0]);
printf(arr[0]1 %p\n, arr[0]1);
printf(arr %p\n, arr);
printf(arr1 %p\n, arr1);
printf(arr %p\n, arr);
printf(arr1 %p\n, arr1);
return 0;
}arr[0] 0077F820 arr[0]1 0077F824 arr 0077F820 arr1 0077F824 arr 0077F820 arr1 0077F848 这⾥我们发现arr[0]和arr[0]1相差4个字节arr和arr1相差4个字节是因为arr[0]和arr都是 ⾸元素的地址1就是跳过⼀个元素。但是arr和arr1相差40个字节这就是因为arr是数组的地址1操作是跳过整个数组的。 到这⾥⼤家应该搞清楚数组名的意义了吧。 数组名是数组⾸元素的地址但是有2个例外
10.使用指针访问数组
有了前⾯知识的⽀持再结合数组的特点我们就可以很⽅便的使⽤指针访问数组了
#include stdio.h
int main()
{ int arr[] { 1,2,3,4,5 };int sz sizeof(arr) / sizeof(arr[0]);int p arr;for (int i 0;i sz;i){scanf(%d, p);p;}p arr;//重置p的位置for (int i 0;i sz;i){printf(%d , p[i]);}return 0;
}p操作让指针挪远之后记得重置p的位置 #include stdio.h
int main()
{ int arr[10] { 0 };int* p arr;int szsizeof(arr)/sizeof(arr[0]);for (int i 0;i sz;i){scanf(%d, p i);//scanf(%d,arri);}for (int i 0;i sz;i){printf(%d , (p i));}return 0;
}将(pi)换成p[i]也是能够正常打印的所以本质上p[i]是等价于(pi)。 同理arr[i] 应该等价于(arri)数组元素的访问在编译器处理的时候也是转换成⾸元素的地址偏移 量求出元素的地址然后解引⽤来访问的
11.一维数组传参的本质
当我们已经有了⼀维数组我们对⼀维数组的处理是否可以使⽤函数呢这样就涉及到将⼀维数组传 递给函数就是⼀维数组传参。 ⽐如我们现在想写⼀个函数打印⼀个整型数组的内容。
#include stdio.h
void test(int arr[], int sz)
{for (int i0;isz;i){printf(%d , arr[i]);}
}
int main()
{ int arr[] { 1,2,3,4,5,6,7,8,9,10 };int sz sizeof(arr) / sizeof(arr[0]);test(arr, sz);return 0;
}我们前⾯是在函数外部计算数组的元素个数那我们可以把函数传给⼀个函数后函数内部求数组的元素个数吗
#include stdio.h
void test(int arr[], int sz)
{printf(%d, sizeof(arr) / sizeof(arr[0]));
}
int main()
{ int arr[] { 1,2,3,4,5,6,7,8,9,10 };int sz sizeof(arr) / sizeof(arr[0]);printf(%d\n, sz);test(arr, sz);return 0;
}我们发现在函数内部是没有正确获得数组的元素个数
这就要学习数组传参的本质了上个⼩节我们学习了数组名是数组⾸元素的地址 那么在数组传参的时候传递的是数组名也就是说本质上数组传参本质上传递的是数组⾸元素的地址。 所以函数形参的部分理论上应该使⽤指针变量来接收⾸元素的地址。
那么在函数内部我们写sizeof(arr) 计算的是⼀个地址的⼤⼩单位字节⽽不是数组的⼤⼩单 位字节。正是因为函数的参数部分是本质是指针所以在函数内部是没办法求的数组元素个数的。 #include stdio.h
void test1(int arr[], int sz)//参数写成数组形式本质上还是指针{printf(%d\n, sizeof(arr));
}
void test2(int* p, int sz)//参数写成指针形式{printf(%d, sizeof(p)); //计算⼀个指针变量的⼤⼩}
int main()
{ int arr[] { 1,2,3,4,5,6,7,8,9,10 };int sz sizeof(arr) / sizeof(arr[0]);test1(arr, sz);test(arr, sz);return 0;
}总结⼀维数组传参形参的部分可以写成数组的形式也可以写成指针的形式。
12.冒泡排序
#include stdio.h
void test1(int*arr,int sz)
{for (int i 0;i sz - 1;i){for (int j 0;j sz - 1 - i;j){if (arr[j] arr[j 1]){int t arr[j];arr[j] arr[j 1];arr[j 1] t;}}}
}
int main()
{ int arr[] { 9,8,7,5,4,6,3,2,10,1 };int sz sizeof(arr) / sizeof(arr[0]);test1(arr, sz);for (int i 0;i sz ;i){printf(%d , arr[i]);}return 0;
}优化
#include stdio.h
void test2(intarr,int sz)
{for (int i 0;i sz - 1;i){ int flag 1;for (int j 0;j sz - 1 - i;j){ if (arr[j] arr[j 1]){ int t arr[j];arr[j] arr[j 1];arr[j 1] t;flag 0;}}if (flag 1)break;}
}
int main()
{ int arr[] { 9,8,7,5,4,6,3,2,10,1 };int sz sizeof(arr) / sizeof(arr[0]);test2(arr, sz);for (int i 0;i sz ;i){printf(%d , arr[i]);}return 0;
}13.二级指针 #include stdio.h
int main()
{int a 10;int b 20;int paa;int const * * ppapa;*ppa b;//等价pabprintf(%d, ppa);//20}*pa解开是整形*ppa解开是pa指针ppa解开也是整形 *ppa可看作(ppa)
#include stdio.h
int main()
{int a 10;int b 20;int paa;int ** ppapa;**ppa 30;//等价于pa30;//等价pa30;printf(%d, **ppa);//30printf(
}#include stdio.h
int main()
{int a 10;int b 20;int paa;int* pb b;int * const * ppapa;ppa pb;printf(%d, ppa);
}可以使二级指针指向另外一个一级指针 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈终于搞懂了
14.指针数组
指针数组是指针还是数组 我们类⽐⼀下整型数组是存放整型的数组字符数组是存放字符的数组。 那指针数组呢是存放指针的数组。 15.指针数组模拟二维数组
#include stdio.h
int main()
{ int arr1[] { 1,2,3,4,5 };int arr2[] { 2,3,4,5,6 };int arr3[] { 3,4,5,6,7 };int* parr[] {arr1,arr2,arr3};for (int i 0;i 3;i){for (int j 0;j 3;j){printf(%d , parr[i][j]);}printf(\n);}return 0;
}arr[i](arri) arr[i][j]x[j](xj) ((arr1)j) 16.字符指针变量 将字符串abcdef首元素a的地址给了p 字符数组可以放字符串且字符数组可以修改如 arr[10]“wasdrrr”; const char*p“abcedf”; 常量字符串和数组非常相似也在一个连续空间存放了多个字符但常量的内容不能修改即*pa’就错误所以加了const 指针数组可以存字符串
17.数组指针变量
17.1数组指针变量是什么 17.2数组指针变量怎么初始化
数组指针变量是⽤来存放数组地址的那怎么获得数组的地址呢就是我们之前学习的数组名 int arr[10] {0};int(*p)[10] arr;18.二维数组传参的本质
过去我们有⼀个⼆维数组的需要传参给⼀个函数的时候⽐如有⼀个整型的⼆维数组写⼀个函数 test打印数组的全部内容。我们可以这样写
#include stdio.h
void test(int arr[3][5], int x, int y)
{for (int i 0;i 3;i){for (int j 0;j 5;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} };test(arr, 3, 5);return 0;
}#include stdio.h
void test(int (*pa)[5], int x, int y)
{for (int i 0;i 3;i){for (int j 0;j 5;j){printf(%d , pa[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} };test(arr, 3, 5);return 0;
}总结⼆维数组传参形参的部分可以写成数组也可以写成指针形式
19.函数指针变量 其实函数也是有地址的我们做个测试
19.1函数指针变量的创建
函数指针变量应该是⽤来存放函数地址的未来通过地址能够调⽤函数的。 如果我们要将函数的地址存放起来就得创建函数指针变量咯函数指针变量的写法其实和数组指针 ⾮常类似。如下
#include stdio.h
void Add(int x,int y)
{return x y;
}
int main()
{ int (*p1)(int,int ) Add;int (*p2)(int x, int y) Add;//x,y可不写return 0;
}19.2函数指针变量的使用
#include stdio.h
void Add(int x,int y)
{return x y;
}
int main()
{ int (*p1)(int,int ) Add;printf(%d, p1(3, 5));//(*p1)return 0;
}19.3两段有趣的代码 19.3.1 typedef 关键字 typedef void((*p_fun)(int));
//typedef int(*p_arr)[5];
p_fun signal(int, p_fun);20.函数指针数组
#include stdio.h
int Add(int x,int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int main()
{int(*parr[])(int ,int) {Add,Sub};printf(%d, parr0);
}21.转移表
#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;
}
int main()
{int (*parr[])(int, int) { NULL,Add,Sub,Div,Mul };int input;do{ int x, y;printf(*1.Add 2.Sub*\n);printf(3.Div 4.Mul*\n);printf(***0.退出游戏*****\n);scanf(%d, input);if (0 input){printf(退出游戏);break;}scanf(%d %d, x, y);int cparrinput;printf(%d, c);} while (input);return 0;
}这个函数数组称作转移表
22.回调函数是什么
回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针地址作为参数传递给另⼀个函数当这个指针被⽤来调⽤其所指向的函数 时被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的⽤于对该事件或条件进⾏响应
#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 cac(int (*pf)(int ,int) )//用所指向函数形式接收
{ int m, n;scanf(%d %d, m, n);int cpf(m,n);printf(%d\n, c);
}
int main()
{int input;do {printf(1.加法\n);printf(2.减法\n);printf(3.乘法\n);printf(4.除法\n);printf(0.退出*\n);scanf(%d, input);switch (input){case 1:cac(Add);break;case 2:cac(Sub);break;case 3:cac(Mul);break;case 4:cac(Div);break;case 0:break;default:printf(输入错误请重新输入);break;}} while (input);return 0;
}23.qsort使用举例
23.1使用qsort函数排序整形数据
#include stdio.h
int paixu(const void e1, const void* e2)
{return (int)e1 - (int)e2;
}
int main()
{ int arr[] { 1,2,5,4,5,7,8,9,6,3 };qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), paixu);int i 0;for (i 0;i sizeof(arr)/sizeof(arr[0]);i){printf(%d , arr[i]);}return 0;
}23.2使用sqort排序结构数据 #include stdio.h
#include stdlib.h
struct stu
{char name[20];int age;
};
int pum1(const void* e1, const void* e2)
{return strcmp(((struct stu)e1)-name, ((struct stu)e2)-name);
}
int main()
{ struct stu arr[3] { {zhangsan,15},{lisi,19},{wangwu,20} };qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), pum1);}strcpm比较俩字符串大小对应位置字符的ASCLL值。 按照年龄来排序想从大到小排只需改变return两边的位置
#include stdio.h
#include stdlib.h
struct stu
{char name[20];int age;
};int pum2(const void* e1, const void* e2)
{return ((struct stu)e1).age - ((struct stu)e2).age;
}
int main()
{ struct stu arr[3] { {zhangsan,15},{lisi,30},{wangwu,20} };qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), pum2);}24.qsort函数的模拟实现
- 上一篇: 网站开发话术seo文章生成器
- 下一篇: 网站开发环境有哪些php微网站 模板
相关文章
-
网站开发话术seo文章生成器
网站开发话术seo文章生成器
- 技术栈
- 2026年03月21日
-
网站开发花费业网站制作
网站开发花费业网站制作
- 技术栈
- 2026年03月21日
-
网站开发后乙方把源代码交给甲方网站建设财务计划与预测
网站开发后乙方把源代码交给甲方网站建设财务计划与预测
- 技术栈
- 2026年03月21日
-
网站开发环境有哪些php微网站 模板
网站开发环境有哪些php微网站 模板
- 技术栈
- 2026年03月21日
-
网站开发获客渠道接网站建设外包的工作总结
网站开发获客渠道接网站建设外包的工作总结
- 技术栈
- 2026年03月21日
-
网站开发及技术wordpress自动备份插件
网站开发及技术wordpress自动备份插件
- 技术栈
- 2026年03月21日
