Почему fread () выдает случайные данные? - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть следующий код C, который открывает файл в режиме rb+, а затем записывает 100 байтов значения 0.Когда я читаю файл со смещением, отличным от 0, я получаю 96. Почему это?

FILE *fp = fopen("myfile", "rb+");
rewind(fp);
char zero = 0;
fwrite(&zero, 1, 100, fp);
char result;
fseek(fp, 1, SEEK_SET);
fread(&result, 1, 1, fp);
printf("%d\n", result);

Я на Linux x64, используя GCC.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Из ваших пояснений в комментариях вы намеревались записать в файл 100 нулевых байтов.Есть как минимум два, а возможно и три способа сделать это.

Первый - выделить массив из 100 инициализированных нулями байтов и записать следующее:

char zeroes[100] = { 0 };
fwrite(zeroes, sizeof(char) /* == 1 */, sizeof(zeroes), f);

Это нехорошо масштабируется, если вы хотите написать, скажем, 10 000 или 10 000 000 нулевых байтов.Вы также можете сделать это:

char zero = 0;
for (int i = 0; i < 100; ++i) fwrite(&zero, sizeof(char), 1, f);

Это масштабируется лучше, но работает очень плохо, так как всегда эффективнее делать одну большую запись, чем много маленьких записей.Вместо этого вы можете искать более позднюю позицию в файле, а затем записывать только последний байт. В системах POSIX это гарантированно для заполнения ранее неписанной части файла нулями:

char zero = 0;
fseek(f, 99, SEEK_SET);
fwrite(&zero, sizeof(char) /* == 1 */, 1, f);

I , поверьте также дается гарантия заполнения нулядля среды выполнения Windows MSVCRT, но я не могу сразу найти доказательства этого на MSDN (это может сделать хороший вопрос).Если кто-то знает, дают ли Windows или другие версии и / или некоторые версии самого стандарта C эту гарантию или нет, этот ответ можно улучшить.

Конечно, если вы * в системе POSIX и не требуют переносимого кода, вы можете использовать ftruncate(), что дает такую ​​же гарантию, даже не делая fwrite().В Windows есть SetEndOfFile() , но , эта функция заполняет расширенную часть файла неопределенными значениями , а не нулевыми байтами.

0 голосов
/ 09 декабря 2018

Вы, вероятно, хотите что-то вроде:

int i; for (i=0;i<100;++i){fwrite(&zero, 1, 1, fp);}

Вы не можете записать 100 байтов из указателя, который указывает на один символ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...