通过由三元条件

时间:2017-04-27 22:10:16

标签: c function pointers function-pointers ternary-operator

我有一个从文件读取数据的函数和另一个将数据写入文件的函数。这些函数类似,仅在被调用的函数freadfwrite上有所不同。所以我想团结他们。但是,我不想写if (read) fread(args); else fwrite(same args);

之类的东西

所以起初我试过这个:

enum { F_READ, F_WRITE };
void rwFile(uint8_t rw, char *name);
...
rwFile(F_READ, name);
...
void rwFile(uint8_t rw, char *name)
{
    FILE *file = fopen(name, (rw == F_READ ? "rb" : "wb"));
    (rw == F_READ ? &fread : &fwrite) (&size, sizeof(size), 1, file);
    for (int i = 0; i < size.Y; i++)
        for (int j = 0; j < size.X; j++)
            (rw == F_READ ? fread : fwrite ) (data[i] + j*2, 2, 1, file);
    fclose(file);
    file = NULL;
}

然后我得到:

main.c: In function ‘rwFile’:
main.c:199:26: warning: pointer type mismatch in conditional expression
  (rw == F_READ ? &fread : &fwrite) (&size, sizeof(size), 1, file);
                         ^
main.c:199:26: error: called object is not a function or function pointer
  (rw == F_READ ? &fread : &fwrite) (&size, sizeof(size), 1, file);
  ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
main.c:202:27: warning: pointer type mismatch in conditional expression
    (rw == F_READ ? fread : fwrite ) (data[i] + j*2, 2, 1, file);
                          ^
main.c:202:27: error: called object is not a function or function pointer
    (rw == F_READ ? fread : fwrite ) (data[i] + j*2, 2, 1, file);
    ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~

好的,让我们尝试另一种变体:

typedef size_t (*rwFunc_t)(const void *ptr, size_t size, size_t count, FILE *stream);
void rwFile(rwFunc_t rwFunc, char *name);
...
rwFile(fread, name);
...
void rwFile(rwFunc_t rwFunc, char *name)
{
    FILE *file = fopen(name, (rwFunc == fread ? "rb" : "wb"));
    (*rwFunc) (&size, sizeof(size), 1, file);
    for (int i = 0; i < size.Y; i++)
        for (int j = 0; j < size.X; j++)
            (*rwFunc) (data[i] + j*2, 2, 1, file);
    fclose(file);
    file = NULL;
}

这很有效。但是,我从gcc收到一些警告:

main.c: In function ‘main’:
main.c:58:10: warning: passing argument 1 of ‘rwFile’ from incompatible pointer type [-Wincompatible-pointer-types]
   rwFile(fread, argv[1]);
          ^~~~~
main.c:18:6: note: expected ‘rwFunc_t {aka long unsigned int (*)(const void *, long unsigned int,  long unsigned int,  struct _IO_FILE *)}’ but argument is of type ‘size_t (*)(void * restrict,  size_t,  size_t,  FILE * restrict) {aka long unsigned int (*)(void * restrict,  long unsigned int,  long unsigned int,  struct _IO_FILE * restrict)}’
 void rwFile(rwFunc_t rwFunc, char *name);
      ^~~~~~
main.c: In function ‘rwFile’:
main.c:198:35: warning: comparison of distinct pointer types lacks a cast
  FILE *file = fopen(name, (rwFunc == fread ? "rb" : "wb"));
                                   ^~

这是因为freadfwrite有一些不同的args:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

那么,它可以以一种很好的方式解决吗?

2 个答案:

答案 0 :(得分:3)

fread()fwrite()的类型 prepared statements不同:

size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);

size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);

请注意constfwrite的{​​{1}}的第一个参数fread {/ 1}}。

你必须克服这种差异。将I / O函数指针传递给函数可能会更清晰,但您可能仍需要使用:

size_t fwrite_alt(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
    return fwrite(ptr, size, nitems, stream);
}

fwrite_alt()的界面与fread()的界面完全匹配。

顺便提一下,请注意,如果您需要生成错误消息,您可能需要有关使用哪个函数的更多信息 - 以及错误消息中使用的单词(以及在您担心I18N / L10N之前的那些 - 国际化和本地化)。您还应该检查读取或写入函数的返回值 - 但是对于短读取和短写入会有不同的含义,这也会使错误处理和报告变得复杂。我不确定你是否会长期想要使用它。

答案 1 :(得分:2)

条件运算符具有以下限制(6.5.15条件运算符)

  

3以下其中一项应适用于第二和第三个操作数:

     

- 两个操作数都是指向合格或非限定版本的指针   兼容类型;

函数freadfwrite具有以下声明

size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);
size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);

正如所见,他们的声明与第一个参数不同。这些参数具有不兼容的类型,因为它们不具有相同的限定条件。结果,这些函数也不兼容,并且可能无法在条件运算符中使用。