深入理解指针(4)

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 div ( int a, int b)
{
return a / b;
}
void calc ( int (*pf)( int , int ))
{
 int ret = 0 ;
 int x, y;
 printf ( " 输⼊操作数: " );
 scanf ( "%d %d" , &x, &y);
 ret = pf(x, y);
 printf ( "ret = %d\n" , ret);
}
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使用举例 

 2.1使用qsort函数排序整型数据

# include <stdio.h>
//qosrt 函数的使⽤者得实现⼀个⽐较函数
int int_cmp ( const void * p1, const void * p2)
{
  return (*( int *)p1 - *( int *) p2);
}
int main ()
{
  int arr[] = { 1 , 3 , 5 , 7 , 9 , 2 , 4 , 6 , 8 , 0 };
  int i = 0 ;
qsort(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 ;
}

2.2 使用qsort排序结构数据 

struct Stu // 学⽣
{
 char name[ 20 ]; // 名字
 int age; // 年龄
};
// 假设按照年龄来⽐较
int cmp_stu_by_age ( const void * e1, const void * e2)
{
 return (( struct Stu*)e1)->age - (( struct Stu*)e2)->age;
}
 //strcmp - 是库函数,是专⻔⽤来⽐较两个字符串的⼤⼩的
 // 假设按照名字来⽐较
int cmp_stu_by_name ( const void * e1, const void * e2)
{
 return strcmp ((( struct Stu*)e1)->name, (( struct Stu*)e2)->name);
}
// 按照年龄来排序
void test2 ()
{
 struct Stu s [] = { { "zhangsan" , 20 }, { "lisi" , 30 }, { "wangwu" , 15 } };
 int sz = sizeof (s) / sizeof (s[ 0 ]);
 qsort(s, sz, sizeof (s[ 0 ]), cmp_stu_by_age);
}
// 按照名字来排序
void test3 ()
{
 struct Stu s [] = { { "zhangsan" , 20 }, { "lisi" , 30 }, { "wangwu" , 15 } };
 int sz = sizeof (s) / sizeof (s[ 0 ]);
 qsort(s, sz, sizeof (s[ 0 ]), cmp_stu_by_name);
}
int main ()
{
 test2();
 test3();
 return 0 ;
}

3.qsort函数的模拟实现 

 使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)。

# 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 };
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.1sizeof

       sizeof计算变量所占内存内存空间大小,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。

      sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。

  比如:
 

#inculde <stdio.h>
int main ()
{
 int a = 10 ;
 printf ( "%d\n" , sizeof (a));
 printf ( "%d\n" , sizeof a);
 printf ( "%d\n" , sizeof ( int ));
return 0 ;
}

最后输出的大小都是4

4.2 strlen

     strlen是C语言库函数,功能是求字符串长度,函数的原型如下:

  size_t strlen ( const char * str );
统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。
strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找。
# include <stdio.h>
int main ()
{
 char arr1[ 3 ] = { 'a' , 'b' , 'c' };
 char arr2[] = "abc" ;
 printf ( "%d\n" , strlen (arr1));
 printf ( "%d\n" , strlen (arr2));
 
 printf ( "%d\n" , sizeof (arr1));
 printf ( "%d\n" , sizeof (arr1));
 return 0 ;
}

4.3 sizeof和strlen的对比

     sizeof:

1. sizeof是操作符
2. sizeof计算操作数所占内存的⼤⼩, 单位是字节
3. 不关注内存中存放什么数据

   strlen:

1. strlen是库函数,使用需要包含头文件string.h

2.srtlen是求字符串⻓度的,统计的是 \0 之前字符的隔个数

3.关注内存中是否有\0,如果没有\0,就会持续的往后找,可能会越界

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值