首页 /  技术专区  /  C 宽屏模式 >

宏深入用法——减少函数定义,简化函数调用

1 使用宏来减少函数定义,简化函数调用

recode_lock.h

#ifndef ___RECODE_LOCK__
#define ___RECODE_LOCK__
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

/* 加非阻塞读锁 */
#define read_lock(fd, l_whence, l_start, l_len) \
lock_set(fd, F_SETLK, F_RDLCK, l_whence, l_start, l_len)

/* 加阻塞读锁 */
#define read_lockw(fd, l_whence, l_start, l_len) \
lock_set(fd, F_SETLKW, F_RDLCK, l_whence, l_start, l_len)

/* 加非阻塞写锁 */
#define write_lock(fd, l_whence, l_start, l_len) \
lock_set(fd, F_SETLK, F_WRLCK, l_whence, l_start, l_len)

/* 加阻塞写锁 */
#define write_lockw(fd, l_whence, l_start, l_len) \
lock_set(fd, F_SETLKW, F_WRLCK, l_whence, l_start, l_len)

/* 解锁 */
#define unlock(fd, l_whence, l_start, l_len) \
lock_set(fd, F_SETLK, F_UNLCK, l_whence, l_start, l_len)

/* 操作锁的函数 */
static int lock_set(int fd, int l_ifwset, short l_type, short l_whence, \
        off_t l_start, off_t l_len)
{
    int ret = -1;
    struct flock f_lock;
    f_lock.l_type = l_type;
    f_lock.l_whence = l_whence;
    f_lock.l_start = l_start;
    f_lock.l_len = l_len;
    ret = fcntl(fd, l_ifwset, &f_lock);//加锁解锁
    return(ret);
}
#endif

helloworld.c 

#include <stdio.h>
#include <stdlib.h>
#include "recode_lock.h"

int main(void)
{
    int ret = 0, fd = -1;
    fd = open("./file", O_CREAT|O_RDWR|O_APPEND|O_TRUNC, 0777);
    if(fd < 0)
    {
        perror("open is fail");
        exit(-1);
    }
    while(1)
    {
        //加阻塞读锁,也就是加锁失败,程序会休眠在这里,就像scanf没有数据,也会休眠一样
        read_lockw(fd, SEEK_SET, 0, 0); 
        write(fd, "hello ", 6);
        write(fd, "world\n", 6);
        unlock(fd, SEEK_SET, 0, 0); //解锁
    }
}			

(1)分析这些宏

        像这类宏参数很多,密密麻麻,很多同学一看到这种宏就讨厌,但是不用担心,分析这类比较复杂的宏定义时是有办法的,办法就是进行宏的替换操作,找到本源后自然就能理解了。

        当然还有一个办法,那就是查看预编译后的替换结果,不过这样还不如层层替换后分析本源来的更直观。


        分析的结果总结:

        所有带参宏的宏体都指向同一个函数lock_set,通过不同的带参宏去调用lock_set函数,就实现了不同的功能,那为什么要这么做呢?为什么不直接定义6个加锁、解锁的函数呢?

(2)为什么要费劲的写这些个复杂的带参宏

        通过前面的介绍我们知道,这个程序的作用是实现对文件的加锁和解锁,可以实现的操作有

            加非阻塞读锁

            加阻塞读锁

            加非阻塞写锁

            加阻塞写锁

            解锁

        其实最终是调用fcntl函数来加锁、解锁的,不过为了调用更方便,我们需要进行进一步的函数封装,其中最笨的方式是定义六个函数,分别是想上述功能。

        但是最后发现一个现象,那就是所有函数想要做的事情都是一样的,都是去设置文件锁的属性,每个函数的代码内容几乎一模一样,函数功能的不同仅仅只是靠参数值的不同来体现的。

        像这种情况,我们定义6个函数来实现,代码其实并不简洁,而且定义这些函数还很花费时间,此时我们就可以使用带参宏来实现,不仅减少了函数的定义,而且还简化了参数。

        能够写死的参数就直接在宏体中写死,调用带参宏时,只填写必须要写的参数。



头像
0/200
图片验证码