為了除錯,將程式碼修改了一下
int main()
{
FILE *img = fopen("image.bmp", "r+b");
if (img == NULL) {
perror("");
return 1;
}
fseek(img, 10, SEEK_SET);
long off = 0;
fread(&off, 4, 1, img);
fseek(img, off, SEEK_SET);
unsigned long buf = 0;
int fread_rv = 0;
while(1){
fread_rv = fread(&buf, 4, 1, img);
printf("fread returned value:%d\n", fread_rv);
if (fread_rv == 0) break;
printf("after reading:%lXh\n", ftell(img));
buf = ((buf << 4) & 0xF0F0F0F0) | ((buf >> 4) & 0xF0F0F0F);
fseek(img, -4, SEEK_CUR);
printf("before writing:%lXh\n", ftell(img));
fwrite(&buf, 4, 1, img);
printf("after writing:%lXh\n\n", ftell(img));
fseek(img, 0, SEEK_CUR);
}
fclose(img);
return 0;
}
這次拿掉while的條件式,多一個fread_rv去接fread的回傳值
改用if來判斷迴圈是否重複執行
執行結果正常,但如果把最後一行fseek去掉則又會陷入無窮迴圈了
,因為fread總是會回傳1
我當下就判斷一定是我在檔案讀寫的使用上有瞭解不清的部分
於是我又到cplusplus查了一遍fseek,發現有句
"On streams open for update (read+write),
a call to fseek allows to switch between reading and writing."
接下來又找到維基教科書裡面有寫在r+b或r+模式下一個output不能馬上接一個input
,除非之間有使用fflush/fseek/fsetpos/rewind,反過來也是類似
之後我用debugger去觀察執行最後一行fseek(img, 0, SEEK_CUR)的效果
發現每次執行完這行,檔案就被修改了一次
所以fseek也是會清空緩衝區並輸出,這應該也是cplusplus那句話的由來
維基教科書提到這部份的連結:
https://en.wikibooks.org/wiki/C_Programming/File_IO#Opening_Files