Проблема записи int в двоичный файл в C - PullRequest
3 голосов
/ 21 апреля 2009

Мне нужно записать данные в двоичный файл, используя функции ввода-вывода C. Следующий код вызывает исключение времени выполнения:


#include "stdio.h"

int main(int argc,char* argv[]) {
    FILE *fp = fopen("path_to_file.bin","wb");
    if(fp == NULL) {
        printf("error creating file");
        return -1;
    }
    int val = 4;
    fwrite((const void*)val,sizeof(int),1,fp);
    fclose(fp);
    return 0;
}

Код умирает на fwrite. Можете ли вы определить, что я делаю не так? Видимо, я пытаюсь получить доступ к данным в 0x0000004 или что-то в этом роде.

Спасибо!

Ответы [ 6 ]

24 голосов
/ 21 апреля 2009

Я думаю, что ответ Нейла может быть улучшен. Я понимаю, что это уже принято, так что это просто чтобы показать некоторый контраст (вот почему я не просто отредактировал его).

fwrite(&val, sizeof val, 1, fp);

Два улучшения:

  • Нет приведения указателя, так как он не нужен в C и может скрывать ошибки.
  • Используйте sizeof непосредственно на объекте, поскольку именно на это вы передаете указатель. Имеет много смысла для меня, и это безопаснее, чем повторять себя и использовать имя типа.
16 голосов
/ 21 апреля 2009
 fwrite((const void*)val,sizeof(int),1,fp);

должно быть:

 fwrite((const void*) & val,sizeof(int),1,fp);

Кстати, если вы не используете приведение, вы получите разумное сообщение об ошибке. Кастинги, как правило, используются программистами на C (и C ++) гораздо чаще, чем они должны быть - хорошее практическое правило гласит: «если для этого требуется приведение, это, вероятно, неправильно».

5 голосов
/ 21 апреля 2009

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

0 голосов
/ 24 февраля 2018

Видимо, я пытаюсь получить доступ к данным в 0x0000004 или что-то в этом роде.

int val = 4

Есть проблема. fwrite предназначен для работы со строками, и поэтому его первым вводом является указатель, расположение строки в памяти. Вы передаете значение val напрямую (4) вместо адреса от val до fwrite; однако память по адресу 0x00000004 не является допустимой памятью программы, и поэтому выдается ошибка.

Чтобы это исправить, измените это:

fwrite((const void*)val,sizeof(int),1,fp);

В это:

fwrite((const void*)&val, sizeof(int), 1, fp);

Оператор «&» указывает местоположение val. Это будет действительный адрес в памяти.

0 голосов
/ 09 ноября 2016

Я тоже сталкивался с такой проблемой. Так что это мое решение.

fwrite(val, sizeof(val[0], sizeof(val)/sizeof(val[0]), fp);

0 голосов
/ 21 апреля 2009
#include "stdio.h"

int main(int argc,char* argv[]) {
    FILE *fp = fopen("path_to_file.bin","wb");
    if(fp == NULL) {
        printf("error creating file");
        return -1;
    }
    int val = 4;
    fwrite((const void*)val,sizeof(int),1,fp);

Вы должны указать адрес, а не целое число.

Кроме того, вы не должны использовать целое число таким образом:

  1. Может отличаться по порядку байтов на разных компьютерах (как уже упоминалось)
  2. Может отличаться по размеру. На действительно старых компьютерах это может быть 1 или 2 байта. На большинстве современных это будет 4, но может также 8 (некоторые 64-битные компьютеры). На некоторых странных архитектурах это может быть даже 36 бит. int32_t val = 4; fwrite((const void *)val, 4, 1, fp) должен решить проблему.

Вы можете подумать, что ваше программное обеспечение никогда не нужно будет переносить. Что ж, многие дизайнеры (программные и аппаратные) сделали подобные предположения. Иногда это слишком дорого, чтобы их не делать - но в этом случае это всего лишь несколько дополнительных проверок.

    fclose(fp);
    return 0;
}
...