Clang对闭包的支持要比Gcc强大。它引入了新的Block的语法,和传统的C语言函数指针并不兼容。Block的语法基本上就是把原来函数指针用*的地方都采用^来替代。比如目录遍历的接口,用Clang Block来定义如下:
- 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);
- }
唯一不同点就是Block的调用语法。函数指针的调用方式为(*visitor)(dp),而Block直接visitor(dp)就可以了。
实现ls很简单:
- void ls(char *dir_name){
-
each(^(struct dirent * dp){
-
printf("%s\n",dp->d_name);
-
}, dir_name);
- }
可以看到Clang的语法更接近函数式编程,比Gcc的nested function更简洁。
用Block实现文件名和文件大小查找也很方便,如下:
- void find(char *dir_name, char *find_str, int min_byte){
-
each(^(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);
-
}
-
}
-
}, dir_name);
- }
本文的所有可运行代码在github上:
代码编译可以用下面的命令:
clang ls.c dir_each.c -I.