仅通过一个操作写入两个文件描述符

我想在C中实现日志记录function,并将消息记录到stdout和某个文件。 我想写一些像fprintf(logout,“msg”); 以某种方式声明FILE * logout,它将字符串重定向到stdout和一些文件。 可能吗?

您显然需要一个类似FILE的对象,将其写入重定向到两个基础FILEstdout和日志文件)。 标准C不允许以任何方式“子类化” FILE对象,因此在C中这是不可能的。但是, GNU libc可以这样做 ,所以如果你的程序只是Linux,你可以通过一些编程来实现。 由于这非常不便携,因此强烈建议不要使用。

实现这一目标的一种更便携的方法是写入管道并创建从管道读取并写入两个底层文件的进程或线程。 例如,假设POSIX:

 FILE *tee_file(FILE *fp1, FILE *fp2) { int fds[2]; if (pipe(fds)) return NULL; switch (fork()) { case 0: { char buf[512]; int nread; FILE *r = fdopen(fds[0], "r"); close(fds[1]); while ((nread = fread(buf, 1, sizeof buf, r)) { fwrite(buf, 1, nread, fp1); fwrite(buf, 1, nread, fp2); } _exit(0); } case -1: return NULL; } close(fds[0]); return fdopen(fds[1], "w"); } /* after calling "fp = tee_file(fp1, fp2)", writes to fp end up in fp1 and fp2. */ 

这两种方法都会给你的程序带来很多复杂性,这应该是一个很好的理由。 你想要的是使用一个记录框架,它允许写入多个输出(它们都可以),或者根据H2CO3的答案编写自己的记录框架。

如果这是在Linux上,您可以打开一个管道到tee命令:

 FILE *logout = popen("tee logfile", "w"); 

你为什么不做自己的记录function?

 int log_fprintf(FILE *stream, const char *restrict fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stream, fmt, args); va_end(args); va_start(args, fmt); int n = vfprintf(stdout, fmt, args); // conceptually, rather `stderr`, please! va_end(args); return n; }