Chinaunix首页 | 论坛 | 博客
  • 博客访问: 60352
  • 博文数量: 15
  • 博客积分: 353
  • 博客等级: 一等列兵
  • 技术积分: 175
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-12 16:15
文章分类
文章存档

2011年(15)

我的朋友

分类: C/C++

2011-12-12 18:01:20

关于GCC 的nested function ,网上有不少深入探讨其实现细节的文章,比如http://blog.linux.org.tw/~jserv/archives/2010/07/gcc_nested_func.html。但是在何时利用nested function上面,我还没有看到有说服力的例子。网上很多介绍nested function语法特性的代码都是为了介绍这个特性而编造出来的。比如下面这个Gcc官网给出的例子

  1. foo (double a, double b)
  2.      {
  3.        double square (double z) { return z * z; }
  4.      
  5.        return square (a) + square (b);
  6.      }
其中的square函数完全可以用正常的函数来定义,而不是定义为嵌套函数。

我认为nested function就应该只用于需要闭包的场合。回到上一篇中提到的目录迭代的例子,我们需要实现下面的接口:
  1. typedef void (*pDirentVisitor)(struct dirent * dp);

  2. extern void each(pDirentVisitor visitor, char *dir_name);
实现这个接口式很简单的:
  1. void each(pDirentVisitor visitor, char *dir_name){
  2.     struct dirent * dp;
  3.     DIR * dirp = opendir(dir_name);
  4.     if(dirp==NULL) return;
  5.     while ((dp = readdir(dirp)) != NULL){
  6.         (*visitor)(dp);
  7.     }
  8.     closedir(dirp);
  9. }
有了这个接口该如何实现ls的功能呢?这时就需要嵌套函数出面了。
  1. void ls(char *dir_name){
  2.     void print_name(struct dirent * dp){
  3.         printf("%s\n",dp->d_name);
  4.     }
  5.     each(print_name, dir_name);
  6. }
和上一篇里面的ls实现代码相比,是不是简单了很多。因为GCC不支持匿名函数,所以上面的代码中的嵌套函数必须要给一个名字“print_name”。如果采用Clang的话,其Block语法则可以连函数定义都不需要,直接通过匿名函数写实现代码,代码会更简洁。Clang的Block会在下一篇中介绍。

用嵌套函数实现文件名和文件大小查找也很方便,如下:
  1. void find(char *dir_name, char *find_str, int min_byte){
  2.     void compare_name_and_size(struct dirent * dp){
  3.         if(strncmp(dp->d_name, find_str, strlen(find_str))==0){
  4.             struct stat    statbuf;
  5.             char buf[1024]={0};
  6.             strcat(buf,dir_name);
  7.             strcat(buf,dp->d_name);
  8.             if (stat(buf, &statbuf) !=-1){
  9.                 if(statbuf.st_size>=min_byte) printf("%s, %d\n",dp->d_name, (int)statbuf.st_size);
  10.             }
  11.         }
  12.     }
  13.     each(compare_name_and_size, dir_name);
  14. }
使用嵌套函数时,函数的定义地点和函数的调用地点不能在一个函数内部,否则就没必要使用嵌套函数。所以 中的代码例子都没有参考价值。

本文的所有可运行代码在github上:
代码编译可以用下面的命令:
gcc -fnested-functions ls.c dir_each.c -I.






阅读(2426) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~