1. 回调函数是什么?
2. qsort使⽤举例
3. qsort函数的模拟实现
4. sizeof和strlen的对⽐
5. 数组和指针笔试题解析
6. 指针运算笔试题解析
正文开始:
1.
回调函数是什么?
回调函数就是⼀个通过
函数指针
调⽤的函数。
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数
时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。
这里的调用函数其实就是通过函数来调用指针(地址)的
函数本身在内部也开辟的一个地址,指针本来也是地址,所以它们是相关的,可以相互调用。
//使⽤回调函数改造前
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x, y;
int input = 1;
int ret = 0;
do
{
printf("******************
printf(" 1:add
printf(" 3:mul
printf("******************
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("输⼊操作数:");
scanf("%d %d", &x, &y)
ret = add(x, y);
printf("ret = %d\n", r
break;
case 2:
printf("输⼊操作数:");
scanf("%d %d", &x, &y)
ret = sub(x, y);
printf("ret = %d\n", r
break;
case 3:
printf("输⼊操作数:");
scanf("%d %d", &x, &y)
ret = mul(x, y);
printf("ret = %d\n", r
break;
case 4:
printf("输⼊操作数:");
scanf("%d %d", &x, &y)
ret = div(x, y);
printf("ret = %d\n", r
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
//使⽤回到函数改造后
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
int main()
{
int input = 1;
do
{
printf("******************
printf(" 1:add
printf(" 3:mul
printf("******************
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(sub);
break;
case 3:
calc(mul);
break;
case 4:
calc(div);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
2.
qsort使⽤举例
3.
qsort函数的模拟实现
使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)。
注意:这⾥第⼀次使⽤
void*
的指针,讲解
void*
的作⽤。
这个的void* 指的就是空指针,也就相当于一个垃圾桶,什么都可以往里面放,可以放不同类型的地址,所以方便传递各种类型
。
#include <stdio.h>
int int_cmp(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}
void _swap(void *p1, void * p2, int size)
{
int i = 0;
for (i = 0; i< size; i++)
{
char tmp = *((char *)p1 + i);
*(( char *)p1 + i) = *((char *) p2 + i);
*(( char *)p2 + i) = tmp;
}
}
void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{
int i = 0;
int j = 0;
for (i = 0; i< count - 1; i++)
{
for (j = 0; j<count-i-1; j++)
{
if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)
{
_swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
}
}
}
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
//char *arr[] = {"aaaa","dddd","cccc","bbbb"};
int i = 0;
bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
{
printf( "%d ", arr[i]);
}
printf("\n");
return 0;
}
4.sizeof和strlen的对⽐
4.1 sizeof
在学习操作符的时候,我们学习了
sizeof
,
sizeof
计算变量
所占内存内存空间⼤⼩的(这里如果有/0也算上的)
,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。
sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。
4.2
strlen
strlen 是C语⾔库函数
,功能是求字符串⻓度。函数原型如下:
size_t strlen ( const char * str );
统计的是从
strlen
函数的参数
str
中这个地址开始向后,
\0
之前字符串中字符的个数。
strlen
函数会⼀直向后找
\0
字符,直到找到为⽌,所以可能存在越界查找。
简单来说就是算/0之前的数,不包活/0,如果没有/0会一直往后找,随时可能越界。
4.3 sizeof 和 strlen的对⽐
sizeof
1. sizeof是操作符
2. sizeof计算操作数所占内
存的⼤⼩,单位是字节
3. 不关注内存中存放什么数
据
strlen
1. strlen是库函数,使⽤需要包含头⽂件 string.h
2. srtlen是求字符串⻓度的,统计的是 \0 之前字符的隔个数
3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能
会越界
5.
数组和指针笔试题解析
5.1
⼀维数组
5.2
字符数组
这里第三*arr的值是多少呢?首先我们知道strlen是/0前面的元素个数,arr数组名,还有*就不是单独的,所以arr表示的是首元素的地址,再*引用,就是表示a,a的类型又是char * 所以就是97,让你算/0前面的元素个数,不是算值97,所以非法访问error
接下来是关于指针的题
5.3
⼆维数组
数组名的意义:
1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表⽰⾸元素的地址。
6.
指针运算笔试题解析
题目一:
题目二:
题目三:
题目四:
完!