У вас есть ряд тонких ошибок, а затем вы проверяете возвращаемое значение fread
против неправильного значения. При вызове fread
нет необходимости ставить перед Buffer4Can
оператор &
( адрес ). Buffer4Can
является массивом и будет преобразован в указатель на первый элемент при доступе (см .: Стандарт C11 - 6.3.2.1 Другие операнды - L-значения, массивы и обозначения функций (p3) )
Когда вы берете адрес Buffer4Can
, вы меняете тип указателя на fread
с uint8_t*
(без &
) на uint8_t (*)[120000)
(с &
тип становится указатель на массив из uint8_t[120000]
). Теперь, по счастливому совпадению, Buffer4Can
является массивом, и указатель на uint8_t
и * указатель на массив uint8_t[120000]
оба будут преобразованы в один и тот же адрес (но имеют совершенно разные типы).
Поскольку они разрешаются по одному и тому же адресу и поскольку fread()
принимает параметр void*
в качестве первого параметра, ошибка остается незаметно для пользователя. (Достаточно сказать, что если вы попытались fread (&Buffer4Can + 1, ...
, то вещи не сработали бы хорошо ...)
Другая проблема, на которую указал @ Domeni c, - это сравнение возврата fread()
. Прототип для fread()
:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Где возвращаемое значение для fread()
:
On success, fread() and fwrite() return the number of items read or
written. This number equals the number of bytes transferred only
when size is 1.
См. man 3 fread
В вашем случае вы предоставляете sizeof(uint8_t)
для параметра size
функции, означающей возврат "This number equals the number of bytes transferred"
или SizeofFile
в вашем случае. Кроме того, точно так же, как sizeof (char)
, sizeof (uint8_t)
равно 1
, поэтому его можно просто представить как 1
.
Единственная другая область, где вам не хватает проверки, - до fread()
, вы необходимо подтвердить SizeofFile <= 120000
, чтобы защитить границы вашего массива. Вы можете положить это вместе со своим вызовом на fread()
как:
if (MAXB < SizeofFile || /* protect bounds/compare return to SizeofFile */
fread (Buffer4Can, 1, SizeofFile, fp) != (size_t)SizeofFile) {
fputs ("error: file exceeds buffer size, or fread failed.\n", stderr);
return 1;
}
( note: тип возврата для fread()
- size_t
, поэтому приведение SizeofFile
необходимо избегать сравнения значений со знаком и без знака)
При использовании типов с точной шириной макросы, используемые как для преобразования ввода, так и для вывода, предоставляются в inttypes.h
(включая саму stdint.h
). Макрос для вывода значения unit8_t
в шестнадцатеричном формате - PRIx8
. Чтобы вывести 8 двухзначных шестнадцатеричных значений на строку, перед которыми стоит "0x"
, вы можете сделать:
for (int i = 0; i < (int)SizeofFile; i++) { /* loop over bytes */
if (i && i % 8 == 0) /* output 8 per-line */
putchar ('\n');
printf (" 0x%02" PRIx8, Buffer4Can[i]); /* use exact width specier */
}
putchar ('\n'); /* tidy up with newline */
( note: макрос PRIx8
находится вне кавычек часть строки формата , она стоит одна. Если бы вы хотели новую строку в конце, строка формата была бы " 0x%02" PRIx8 "\n"
)
С то, что вы программируете, должно функционировать по вашему желанию. Обратите внимание, что имя файла для чтения требуется в качестве первого аргумента программы, или, если ничего не указано, оно будет считано из stdin
по умолчанию (вы можете перенаправить двоичный файл в stdin
). В целом, вы можете сделать что-то похожее на:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#define MAXB 120000 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
uint8_t Buffer4Can[MAXB]; /* buffer to hold bytes from file */
long SizeofFile; /* size of file (note type long for ftell) */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
fseek (fp, 0, SEEK_END); /* seek end */
SizeofFile = ftell(fp); /* get lenght */
rewind (fp); /* rewind to beginning */
if (MAXB < SizeofFile || /* protect bounds/compare return to SizeofFile */
fread (Buffer4Can, 1, SizeofFile, fp) != (size_t)SizeofFile) {
fputs ("error: file exceeds buffer size, or fread failed.\n", stderr);
return 1;
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (int i = 0; i < (int)SizeofFile; i++) { /* loop over bytes */
if (i && i % 8 == 0) /* output 8 per-line */
putchar ('\n');
printf (" 0x%02" PRIx8, Buffer4Can[i]); /* use exact width specier */
}
putchar ('\n'); /* tidy up with newline */
}
( note: все лишние переменные удалены, и обратите внимание, что тип возвращаемого значения для ftell()
равен long
, не int
)
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.