我可以写文件而不分配缓冲区

时间:2019-01-04 01:30:37

标签: c file

是否可以使用fwrite或其他文件写入功能而不将缓冲区分配给变量?

鉴于我的数据是一个简单的常量uint8_t,因此有比这更好的方法

const uint8_t a = 'A';
const uint8_t b = 'B';

if (cond)
   fwrite(&a, 1, 1, out_file);
else
   fwrite(&b, 1, 1, out_file);

编辑:对于单个字符,存在fputc(由于我正在寻找写入,因此未出现在搜索中)。有什么办法可以处理ints等多字节数据?

我正在寻找防止使用此类代码的方法

const uint16_t val1 = CONST_1;
const uint16_t val2 = CONST_2;
const uint16_t val3 = CONST_3;
const uint16_t val4 = CONST_4;
const uint16_t val5 = CONST_5;

if (cond1)      { fwrite(&val1, sizeof(val1), 1, out_file); }
else if (cond2) { fwrite(&val1, sizeof(val1), 1, out_file); }
// etc

不仅仅是简单地

if (cond1)      { fputint(CONST_1, out_file); }
else if (cond2) { fputint(CONST_2, out_file); }
// etc

4 个答案:

答案 0 :(得分:1)

  

我可以写没有缓冲区的文件吗(?)

     

鉴于我的数据是一个简单的常量uint8_t,有没有比...更好的方法?

考虑下面的2条。在两种情况下,a 都是缓冲区。 @Eric Postpischil

const uint8_t a = 'A';
fwrite(&a, 1, 1, out_file);
fputc(a, out_file);

这些天来,多么好的编译器真是令人惊讶。两行代码都可能发出相同的代码。编写清晰代码,让编译器处理真正微优化的问题。


  

是否可以对int之类的多字节数据进行处理?

int i = rand();
fwrite(&i, sizeof i, 1, out_file);

答案 1 :(得分:1)

您需要区分运行时存在的值和仅在编译过程中存在的值。

在运行时,编译到程序数据部分的任何值都存在于某个地址,对于按引用传递的多字节值是规范(对于64位以上的位值,这是唯一可行的选择)。这也意味着仅在编译时存在的值无法直接寻址,这主要是宏(如枚举)。枚举通常在运行时静态使用,这意味着它们可能永远不会离开程序段并变为可寻址状态。

但是,允许您为常量重用变量,这是两个使用原始posix / linux写入的示例:

#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>

enum {
    FIRST = 10000,
    SECOND,
    THIRD
};

//This can (and probably will automatically) be inlined
void write_constant(uint16_t val, int fd)
{
    write(fd, &val, sizeof(val));
}

int main (void)
{
    int fd;
    uint16_t out;
    fd = open("/tmp/testfile", O_CREAT | O_WRONLY, 0640);

    //First example, reusing variable and assigning compile time constants:
    out = FIRST;  write(fd, &out, sizeof(out));
    out = SECOND; write(fd, &out, sizeof(out));
    out = THIRD;  write(fd, &out, sizeof(out));

    //Second example, wrapping the write in a function
    //This wraps the value inside an uint16_t value on either stack or register:
    write_constant(FIRST,fd);
    write_constant(SECOND,fd);
    write_constant(THIRD,fd);

    close(fd);
    return 0;
}

在不使用格式化程序的情况下直接写入多个整数时要注意的一件事是,程序的字节序保留在文件中,并且大多数人不可读。

答案 2 :(得分:1)

我们可以使用compound literals

if (cond)
   fwrite((uint8_t[]){'A'}, 1, 1, out_file);
else
   fwrite((uint8_t[]){'B'}, 1, 1, out_file);

答案 3 :(得分:0)

  

是否可以在不将缓冲区分配给变量的情况下使用fwrite或其他文件写入功能?

当然,您可以编写文字字符串,例如

fwrite("\1", 1, 1, file);

fwrite("\2\3\0\17", 4, 1, file);

在后面的示例中,字符串在第三个位置包含一个 NUL 字节。

但是请记住,二进制格式实际上是与某些体系结构绑定在一起的(在某些ARM上很难读取用x86编写的二进制文件,例如,因为这些处理器具有不同的endianess)。

当然,如果应该使用文字字符串将几个字节编码为整数,则应该注意endianess。然后使用复合文字(如answered by Kamil Cuk)应该更容易。

实际上,您可能更喜欢serialization技术(因为像XDR这样的二进制格式与体系结构无关),在某些情况下,您希望使用textual这样的格式JSON,{ {3}}等...(因为它们更易于调试)。您会找到可以帮助您的库。