主题:[讨论]《Linux C编程一站式学习》的一个错误,欢迎讨论
第 24 章 函数接口 5. 回调函数 例 24.7. 回调函数
[code=c]
/* para_callback.h */
#ifndef PARA_CALLBACK_H
#define PARA_CALLBACK_H
typedef void (*callback_t)(void *);
extern void repeat_three_times(callback_t, void *);
#endif
[/code]
[code=c]
/* para_callback.c */
#include "para_callback.h"
void repeat_three_times(callback_t f, void *para)
{
f(para);
f(para);
f(para);
}
[/code]
[code=c]
/* main.c */
#include <stdio.h>
#include "para_callback.h"
void say_hello(void *str)
{
printf("Hello %s\n", (const char *)str);
}
void count_numbers(void *num)
{
int i;
[color=Green] for(i=1; i<=(int)num; i++)[/color]
printf("%d ", i);
putchar('\n');
}
int main(void)
{
repeat_three_times(say_hello, "Guys");
repeat_three_times(count_numbers, (void *)4);
return 0;
}
[/code]
编译main.c没有通过,报错如下:
[code=c]
main.c: In function 'count_numbers':
main.c:12: warning: cast from pointer to integer of different size
[/code]
大致一看,根据参数类型,传入的是void *指针,调用时直接用num来取值,没问题啊。(我以前没注意过这个问题,根据例子猜想的。)
然后我试验了这个想法:
源代码:
[code=c]
#include <stdio.h>
void printnum(int *num)
{
printf("%d\n",num);
}
int main(void)
{
int i = 3;
printnum(&i);
return 0;
}
[/code]
编译通过,运行结果是一个随机数。
改为
[code=c]
#include <stdio.h>
void printnum(int *num)
{
[color=Green] printf("%d\n",*num);[/color]
}
int main(void)
{
int i = 3;
printnum(&i);
return 0;
}
[/code]
正确运行。
想想传送函数的是指针,已经不是在main函数里面的变量了,所以一切都应该严格按照指针来操作。
由此更改原先的代码(main.c):
[code=c]
/* main.c */
#include <stdio.h>
#include "para_callback.h"
void say_hello(void *str)
{
printf("Hello %s\n", (const char *)str);
}
void count_numbers(void *num)
{
int i;
for(i=1; i<=*((int *)num); i++)[/color]
printf("%d ", i);
putchar('\n');
}
int main(void)
{
repeat_three_times(say_hello, "Guys");
repeat_three_times(count_numbers, (void *)4);
return 0;
}
[/code]
可以顺利编译,运行出现Segmentation fault。
问题锁定在(void *)4
俺菜鸟一只,还真不晓得C语言能不能取常量的地址,网上搜索无果。那么就暂时认为不可以吧。
修改
[code=c]
int main(void)
{
int i = 4;
repeat_three_times(say_hello, "Guys");
repeat_three_times(count_numbers, (void *)&i);
return 0;
}
[/code]
正确运行。
我的分析就是这样了,贴出来,是想让高手们看看我哪里是不是出现问题,因为我感觉这本书写得很专业并且很认真,会不会是编译器的问题?
[code=c]
/* para_callback.h */
#ifndef PARA_CALLBACK_H
#define PARA_CALLBACK_H
typedef void (*callback_t)(void *);
extern void repeat_three_times(callback_t, void *);
#endif
[/code]
[code=c]
/* para_callback.c */
#include "para_callback.h"
void repeat_three_times(callback_t f, void *para)
{
f(para);
f(para);
f(para);
}
[/code]
[code=c]
/* main.c */
#include <stdio.h>
#include "para_callback.h"
void say_hello(void *str)
{
printf("Hello %s\n", (const char *)str);
}
void count_numbers(void *num)
{
int i;
[color=Green] for(i=1; i<=(int)num; i++)[/color]
printf("%d ", i);
putchar('\n');
}
int main(void)
{
repeat_three_times(say_hello, "Guys");
repeat_three_times(count_numbers, (void *)4);
return 0;
}
[/code]
编译main.c没有通过,报错如下:
[code=c]
main.c: In function 'count_numbers':
main.c:12: warning: cast from pointer to integer of different size
[/code]
大致一看,根据参数类型,传入的是void *指针,调用时直接用num来取值,没问题啊。(我以前没注意过这个问题,根据例子猜想的。)
然后我试验了这个想法:
源代码:
[code=c]
#include <stdio.h>
void printnum(int *num)
{
printf("%d\n",num);
}
int main(void)
{
int i = 3;
printnum(&i);
return 0;
}
[/code]
编译通过,运行结果是一个随机数。
改为
[code=c]
#include <stdio.h>
void printnum(int *num)
{
[color=Green] printf("%d\n",*num);[/color]
}
int main(void)
{
int i = 3;
printnum(&i);
return 0;
}
[/code]
正确运行。
想想传送函数的是指针,已经不是在main函数里面的变量了,所以一切都应该严格按照指针来操作。
由此更改原先的代码(main.c):
[code=c]
/* main.c */
#include <stdio.h>
#include "para_callback.h"
void say_hello(void *str)
{
printf("Hello %s\n", (const char *)str);
}
void count_numbers(void *num)
{
int i;
for(i=1; i<=*((int *)num); i++)[/color]
printf("%d ", i);
putchar('\n');
}
int main(void)
{
repeat_three_times(say_hello, "Guys");
repeat_three_times(count_numbers, (void *)4);
return 0;
}
[/code]
可以顺利编译,运行出现Segmentation fault。
问题锁定在(void *)4
俺菜鸟一只,还真不晓得C语言能不能取常量的地址,网上搜索无果。那么就暂时认为不可以吧。
修改
[code=c]
int main(void)
{
int i = 4;
repeat_three_times(say_hello, "Guys");
repeat_three_times(count_numbers, (void *)&i);
return 0;
}
[/code]
正确运行。
我的分析就是这样了,贴出来,是想让高手们看看我哪里是不是出现问题,因为我感觉这本书写得很专业并且很认真,会不会是编译器的问题?