指针

4 篇文章 0 订阅
1 篇文章 0 订阅

指针与数组

输出数组名,数组名是固定的,指向数组的指针变量却是灵活可变的

指针与函数

输出函数名,函数名是固定的,指向函数的指针变量却是灵活可变的

在下面的例子中,getfile函数用来在备份/还原过程中处理文件,它接受两个参数,fill和skip(都是指向函数的指针)。这两个参数用来指示如何读取或跳过数据。

/*
 * Extract a file from the tape.
 * When an allocated block is found it is passed to the fill function;
 * when an unallocated block (hole) is found, a zeroed buffer is passed
 * to the skip function.
 */
void
getfile(fill, skip)
    void    (*fill) __P((char *, long));
    void    (*skip) __P((char *, long));
{
    int i;
    int curblk = 0;
    quad_t size = spcl.c_dinode.di_size;
    static char clearedbuf[MAXBSIZE];
    char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
    char junk[TP_BSIZE];

#ifdef __GNUC__         /* XXX: to shut up gcc warnings */
    (void)&curblk;
    (void)&size;
#endif

    if (spcl.c_type == TS_END)
        panic("ran off end of tape\n");
    if (spcl.c_magic != NFS_MAGIC)
        panic("not at beginning of a file\n");
    if (!gettingfile && setjmp(restart) != 0)
        return;
    gettingfile++;
loop:
    for (i = 0; i < spcl.c_count; i++) {
        if (spcl.c_addr[i]) {
            readtape(&buf[curblk++][0]);
            if (curblk == fssize / TP_BSIZE) {
                (*fill)((char *)buf, (long)(size > TP_BSIZE ?
                     fssize : (curblk - 1) * TP_BSIZE + size));
                curblk = 0;
            }
        } else {
            if (curblk > 0) {
                (*fill)((char *)buf, (long)(size > TP_BSIZE ?
                     curblk * TP_BSIZE :
                     (curblk - 1) * TP_BSIZE + size));
                curblk = 0;
            }
            (*skip)(clearedbuf, (long)(size > TP_BSIZE ?
                TP_BSIZE : size));
        }
        if ((size -= TP_BSIZE) <= 0) {
            for (i++; i < spcl.c_count; i++)
                if (spcl.c_addr[i])
                    readtape(junk);
            break;
        }
    }
    if (gethead(&spcl) == GOOD && size > 0) {
        if (spcl.c_type == TS_ADDR)
            goto loop;
        dprintf(stdout,
            "Missing address (header) block for %s at %d blocks\n",
            curfile.name, blksread);
    }
    if (curblk > 0)
        (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size));
    findinode(&spcl);
    gettingfile = 0;
}

借助函数指针,开发者还可以参数化代码体的控制流程,在下面的例子中,closefunc保存着关闭fin流时需要调用的函数指针。在运行时,实际调用的函数取决于fin流的打开方式。

void
retrieve(cmd, name)
    char *cmd, *name;
{
    FILE *fin = NULL, *dout;
    struct stat st;
    int (*closefunc) __P((FILE *)) = NULL;
    int log;

    log = (cmd == 0);
    if (cmd == 0) {
        fin = fopen(name, "r"), closefunc = fclose;
        if (fin == NULL)
            cmd = do_conversion(name);
    }
    if (cmd) {
        char line[BUFSIZ];

        (void)snprintf(line, sizeof(line), cmd, name), name = line;
        fin = ftpd_popen(line, "r", 1), closefunc = ftpd_pclose;
        st.st_size = -1;
        st.st_blksize = BUFSIZ;
    }
    if (fin == NULL) {
        if (errno != 0) {
            perror_reply(550, name);
            if (log) {
                LOGCMD("get", name);
            }
        }
        return;
    }
    byte_count = -1;
    if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
        reply(550, "%s: not a plain file.", name);
        goto done;
    }
    if (restart_point) {
        if (type == TYPE_A) {
            off_t i, n;
            int c;

            n = restart_point;
            i = 0;
            while (i++ < n) {
                if ((c=getc(fin)) == EOF) {
                    perror_reply(550, name);
                    goto done;
                }
                if (c == '\n')
                    i++;
            }
        } else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
            perror_reply(550, name);
            goto done;
        }
    }
    dout = dataconn(name, st.st_size, "w");
    if (dout == NULL)
        goto done;
    send_data(fin, dout, st.st_blksize);
    (void) fclose(dout);
    data = -1;
    pdata = -1;
done:
    if (log)
        LOGBYTES("get", name, byte_count);
    (*closefunc)(fin);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值