Почему fgetc читает только определенный байт PNG в C?

Я пытаюсь прочитать байты файла изображения на C, в частности PNG, следующим образом:

#include <stdio.h>

int main(){
  FILE* fd = fopen("logo.png", "r");
  char c = fgetc(fd);
  while(c != EOF){
    printf("%c", c);
    c = fgetc(fd);
  }
  return 0;
}

Когда я запускаю программу, я получаю следующее:

<89>PNG^M
^Z
^@^@^@^MIHDR^@^@^@

Почему он переходит только к определенному байту, а затем полностью прекращает чтение файла? Как мне исправить эту проблему?


person user3864563    schedule 27.01.2017    source источник
comment
Также fopen("logo.png", "r"); - ›fopen("logo.png", "rb"); Открыть в двоичном режиме.   -  person chux - Reinstate Monica    schedule 27.01.2017
comment
Было бы лучше использовать rb по сравнению с r? Просто хочу понять разницу между использованием.   -  person user3864563    schedule 27.01.2017
comment
Некоторые системы выполняют переводы файлов в текстовом режиме. (нет "b") как \r\n ‹==› \r. Файлы .png являются бинарными (добавить "b"). Перевод не нужен.   -  person chux - Reinstate Monica    schedule 27.01.2017


Ответы (1)


Код содержит ошибку.

// Wrong
char c = fgetc(fd);

Правильная версия:

// Correct
int c = fgetc(fd);

Происходит то, что байт 0xff появляется где-то в вашем PNG-файле. Итак, вы получаете:

char c = 0xff;

Но это переполнение, и в этом случае это приводит к:

char c = -1;

И EOF тоже -1.

(Обратите внимание: если вы прочитаете стандарт C, выяснится, что мы действительно столкнулись с неопределенным поведением, но обсуждение неопределенного поведения может превратиться в кроличью нору.)

person Dietrich Epp    schedule 27.01.2017
comment
Мне нравится последний комментарий: D - person P0W; 27.01.2017
comment
Спасибо! Это исправило ошибку, которая была в моей программе. Символ, на котором застрял мой код, был \ 377. Я знал, что у персонажа была проблема, но то, что происходило, сбивало меня с толку. - person user3864563; 27.01.2017