- Когда я использую
fwrite
tostdout
, это становится неопределенным результатом? - Какая польза от аргумента
size_t count
в функцияхfwrite
иfread
?
#include<stdio.h>
struct test
{
char str[20];
int num;
float fnum;
};
int main()
{
struct test test1={"name",12,12.334};
fwrite(&test1,sizeof(test1),1,stdout);
return 0;
}
Выход:
name XEA
Process returned 0 (0x0) execution time : 0.180 s
Press any key to continue.
И когда я использую FWRITE для файла
#include<stdio.h>
#include<stdlib.h>
struct test
{
char str[20];
int num;
float fnum;
};
int main()
{
struct test test1={"name",12,12.334};
FILE *fp;
fp=fopen("test.txt","w");
if(fp==NULL)
{
printf("FILE Error");
exit(1);
}
fwrite(&test1,sizeof(test1),1,fp);
return 0;
}
Файл также содержит подобное
name XEA
- Почему вывод такой?
- И когда я ставлю
size_t count
как 5, он также становится неопределенным результатом. Какова цель этого аргумента?
1 ответ
Таким образом, вы используете его, fwrite
- это запись «двоичного» выхода, которое представляет собой байтовое представление вашего struct test
, как в памяти. Это представление не , как правило, читаемое человеком.
Когда ты пишешь
struct test test1 = {"name", 12, 12.334};
Вы получаете структуру в памяти, которая может быть представлена следующим образом (со всеми байтовыми значениями в шестнадцатеричном формате):
test1: str: 6e 61 6d 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
num: 0c 00 00 00
fnum: 10 58 45 41
В частности: 0x6e
, 0x6d
, 0x6d
, а 0x65
, и 0x65
- коды ASCII для букв в "name"
. Ваш массив {str
был размером 20, поэтому строка name
равен 0, а затем прокладывается с 15 более 0 символов. 0x0c
- шестнадцатеричное представление № 12, и я предполагаю, что тип int
- 32 бита или 4 байта на вашем компьютере, поэтому есть еще 3 0, также. (Также я предполагаю, что ваша машина - «маленький Endian», с наименее значимым байтом 4-байтового количества, подобного 0x0000000c
, находящихся первым в памяти.) Наконец, в формат IEEE-754 который использует вашу машину, номер 12.334 представлен в 32-разрядной точке с плавающей точкой одной точности AS {{x10} }, который снова хранится в противоположном порядке в памяти.
Таким образом, эти 28 байтов (плюс, возможно, некоторые дополнения, о которых мы пока не будем беспокоиться) - это именно те байты, которые записываются на экран или в ваш файл. Строка «name», вероятно, будет удобочитаема, но все остальное будет буквально «двоичным мусором. ". Так уж получилось, что три байта, составляющие число с плавающей запятой 12.334, а именно 0x58
, 0x45
и 0x41
, соответствуют в ASCII заглавным буквам X
, { {X4}} и A
, поэтому вы видите эти символы в выводе.
Вот результат прохождения вывода вашей программы в «Hex Dump Утилита:
0 6e 61 6d 65 00 00 00 00 00 00 00 00 00 00 00 00 name............
16 00 00 00 00 0c 00 00 00 10 58 45 41 .........XEA
Вы можете видеть буквы name
в начале и буквы XEA
в конце, а также все нули и другие двоичные символы между ними.
Если вы находитесь в системе Unix или Linux (или Mac OS X), вы можете использовать такие инструменты, как od
или hexdump
, чтобы получить Шестник свалка, похожий на тот, который я показал.
Вы спросили об аргументе "счетчик" для fwrite
. fwrite
буквально предназначен для записи двоичных структур, как и вы. Его функциональная подпись
size_t fwrite(void *ptr, size_t sz, size_t n, FILE *fp);
Как вы знаете, ptr
- указатель на структуру (ы) данных, которые вы пишете, и fp
указатель файла вы пишете это / их. И тогда вы говорите, что хотите написать n
(или «count») элементы, каждый размер sz
.
Вы назвали
fwrite(&test1, sizeof(test1), 1, fp);
Выражение sizeof(test1)
дает размер test1
в байтах. (Вероятно, будет 28 или около того, как я упоминал выше.) И, конечно, вы пишете одну структуру, поэтому передаете sizeof(test1)
и 1
как sz
и n
совершенно разумно и правильно.
Это также не было бы неразумно или неверно позвонить
fwrite(&test1, 1, sizeof(test1), fp);
Теперь вы говорите fwrite
записать 28 байтов, каждый размером 1. (Байт, конечно, всегда имеет размер 1.)
Еще одна вещь о fwrite
(как отмечено @anttihaapala в комментарии): когда вы пишете двоичные данные в файл, вы должны указать флаг b
, когда вы открываете файл:
fp = fopen("test.txt", "wb");
Наконец, если это не то, что вам нужно, если вместо этого вы хотите выводить текст, читаемый человеком, то {{X 0}} здесь не то, что вам нужно. Вы можете использовать что-то вроде
printf("str: %s\n", test1.str);
printf("num: %d\n", test1.num);
printf("fnum: %f\n", test1.fnum);
Или к вашему файлу:
fprintf(fp, "str: %s\n", test1.str);
fprintf(fp, "num: %d\n", test1.num);
fprintf(fp, "fnum: %f\n", test1.fnum);
Похожие вопросы
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.