Могу ли я писать в файлы без назначения буфера - PullRequest
0 голосов
/ 04 января 2019

Есть ли способ использовать 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 (не появлялся в моих поисках, потому что я искал запись).Есть ли способ сделать это для многобайтовых данных, таких как целые числа?

Я ищу способы предотвратить использование такого рода кода

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 голосов
/ 05 января 2019

Есть ли способ использовать fwrite или другую функцию записи в файл без назначения буфера переменной?

Конечно, вы можете написать буквальную строку, например,

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

или

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

В последнем примере строка содержит NUL байт в третьей позиции.

Однако помните, что двоичные форматы на практикепривязан к некоторой архитектуре (на некоторых ARM будет непросто прочитать двоичный файл, написанный на x86, например, потому что эти процессоры имеют различную endianess ).

Конечно, вы должны заботиться о endianess , если предполагается, что эта литеральная строка кодирует целое число в несколько байтов.Тогда использование составных литералов, как ответил Камиль Цук , должно быть проще.

На практике вы можете предпочесть сериализация метод (потому что двоичные форматы, такие как XDR) не зависят от архитектуры), а в некоторых случаях вам нужны текстовые форматы, такие как JSON , YAML и т. Д .... (потому что их легчеотладки).Вы найдете библиотеки, которые помогут вам.

0 голосов
/ 05 января 2019

Необходимо различать значения, существующие во время выполнения, и значения, которые существуют только во время компиляции.

Любое значение, скомпилированное в раздел данных программы, существует по адресу во время выполнения и для многобайтовогоПередача значений по ссылке является нормой (и единственный практический выбор для 64-битных значений).Это также означает, что значения, которые существуют только во время компиляции, не могут быть адресованы напрямую, это в основном макросы (например, перечисления).Перечисления, как правило, используются статически во время выполнения, что означает, что они могут никогда не покинуть программный раздел и стать адресуемыми.

Однако вы можете повторно использовать переменные для своих констант, вот два примера, использующих raw posix / linuxwrite:

#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;
}

При записи нескольких целых чисел напрямую без средства форматирования следует отметить одну вещь: порядковый номер программы сохраняется в файле и в большинстве случаев он не читается человеком.

0 голосов
/ 05 января 2019

Мы можем использовать составные литералы .

if (cond)
   fwrite((uint8_t[]){'A'}, 1, 1, out_file);
else
   fwrite((uint8_t[]){'B'}, 1, 1, out_file);
0 голосов
/ 04 января 2019

Можно ли записывать в файлы без буфера (?)

Учитывая тот факт, что мои данные являются простыми константами uint8_t есть ли лучший способ, чем ...?

Рассмотрим 2 записи ниже.В обоих случаях a является буфером. @ Eric Postpischil

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

Удивительно, насколько хороши компиляторы в наши дни.Вполне возможно, что обе строки кода могут испускать один и тот же код.Код для ясности и позвольте компилятору разобраться с тем, что на самом деле является задачей микрооптимизации.


Есть ли способ сделать это для многобайтовых данных, таких как int s?

int i = rand();
fwrite(&i, sizeof i, 1, out_file);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...