指针

来源:互联网 发布:php门户网站源码 编辑:程序博客网 时间:2024/06/06 01:09

指针与数组

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

指针与函数

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

在下面的例子中,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. */voidgetfile(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流的打开方式。

voidretrieve(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
原创粉丝点击