关于GCC 的nested function ,网上有不少深入探讨其实现细节的文章,比如http://blog.linux.org.tw/~jserv/archives/2010/07/gcc_nested_func.html。但是在何时利用nested function上面,我还没有看到有说服力的例子。网上很多介绍nested function语法特性的代码都是为了介绍这个特性而编造出来的。比如下面这个Gcc官网给出的例子
- foo (double a, double b)
- {
- double square (double z) { return z * z; }
-
- return square (a) + square (b);
- }
其中的square函数完全可以用正常的函数来定义,而不是定义为嵌套函数。
我认为nested function就应该只用于需要闭包的场合。回到上一篇中提到的目录迭代的例子,我们需要实现下面的接口:
- typedef void (*pDirentVisitor)(struct dirent * dp);
-
-
extern void each(pDirentVisitor visitor, char *dir_name);
实现这个接口式很简单的:
- void each(pDirentVisitor visitor, char *dir_name){
-
struct dirent * dp;
-
DIR * dirp = opendir(dir_name);
-
if(dirp==NULL) return;
-
while ((dp = readdir(dirp)) != NULL){
-
(*visitor)(dp);
-
}
-
closedir(dirp);
-
}
有了这个接口该如何实现ls的功能呢?这时就需要嵌套函数出面了。
- void ls(char *dir_name){
-
void print_name(struct dirent * dp){
-
printf("%s\n",dp->d_name);
-
}
-
each(print_name, dir_name);
-
}
和上一篇里面的ls实现代码相比,是不是简单了很多。因为GCC不支持匿名函数,所以上面的代码中的嵌套函数必须要给一个名字“print_name”。如果采用Clang的话,其Block语法则可以连函数定义都不需要,直接通过匿名函数写实现代码,代码会更简洁。Clang的Block会在下一篇中介绍。
用嵌套函数实现文件名和文件大小查找也很方便,如下:
- void find(char *dir_name, char *find_str, int min_byte){
-
void compare_name_and_size(struct dirent * dp){
-
if(strncmp(dp->d_name, find_str, strlen(find_str))==0){
-
struct stat statbuf;
-
char buf[1024]={0};
-
strcat(buf,dir_name);
-
strcat(buf,dp->d_name);
-
if (stat(buf, &statbuf) !=-1){
-
if(statbuf.st_size>=min_byte) printf("%s, %d\n",dp->d_name, (int)statbuf.st_size);
-
}
-
}
-
}
-
each(compare_name_and_size, dir_name);
-
}
使用嵌套函数时,函数的定义地点和函数的调用地点不能在一个函数内部,否则就没必要使用嵌套函数。所以 中的代码例子都没有参考价值。
本文的所有可运行代码在github上:
代码编译可以用下面的命令:
gcc -fnested-functions ls.c dir_each.c -I.
阅读(2426) | 评论(0) | 转发(0) |