我有一个从文件读取数据的函数和另一个将数据写入文件的函数。这些函数类似,仅在被调用的函数fread
和fwrite
上有所不同。所以我想团结他们。但是,我不想写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"));
^~
这是因为fread
和fwrite
有一些不同的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);
那么,它可以以一种很好的方式解决吗?
答案 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);
请注意const
中fwrite
的{{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以下其中一项应适用于第二和第三个操作数:
- 两个操作数都是指向合格或非限定版本的指针 兼容类型;
函数fread
和fwrite
具有以下声明
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);
正如所见,他们的声明与第一个参数不同。这些参数具有不兼容的类型,因为它们不具有相同的限定条件。结果,这些函数也不兼容,并且可能无法在条件运算符中使用。