fseek函数SEEK_CUR模式下0偏移的作用?移除后为何死循环
为什么移除
fseek(file, 0, SEEK_CUR)会导致死循环? 以下代码用于将二进制文件中每个Product结构体实例的价格翻倍,原本可正常运行:
while (fread(&product, sizeof(Product), 1, file) == 1) { product.price *= 2.0; fseek(file, -sizeof(Product), SEEK_CUR); fwrite(&product, sizeof(Product), 1, file); fseek(file, 0, SEEK_CUR); }
按逻辑推导:
fread读取完一条记录后,文件指针会自动跳至下一条记录的起始位置- 第一个
fseek将指针移回当前记录开头,方便fwrite覆盖更新 fwrite完成后,指针又会自动跳至下一条记录位置,照理说下一次fread应该能继续读取下一条,循环正常推进
但实际测试发现,移除fseek(file, 0, SEEK_CUR);后代码会进入死循环,用ftell观察发现这条语句执行前后指针值完全没变,实在搞不懂它的必要性。
问题根源:标准库的流同步规则
这是因为在读写操作交替进行时,流的位置状态可能处于未定义状态,必须通过fseek或fsetpos这类操作来同步位置状态。
虽然ftell显示指针值没变化,但fseek(file, 0, SEEK_CUR)的核心作用不是移动指针,而是强制让标准库同步内部的读写位置缓存:
- 当你先执行
fread再切换到fwrite时,流的状态从"读模式"切换到"写模式",此时标准库的内部位置指针可能处于模糊状态——它知道当前字节位置,但未明确完成读写状态的切换同步。 - 如果直接再次调用
fread,标准库可能无法正确更新位置,导致下一次fread又读取了刚刚修改过的同一条记录,从而进入死循环。 fseek(file, 0, SEEK_CUR)看似没移动指针,但它会触发流的位置同步,让标准库明确当前的位置状态,确保下一次fread能正确读取下一条记录。
简单说,这条语句是给标准库一个"明确位置、切换状态"的信号,表面上没动指针,但内部完成了必要的同步操作,避免了死循环。
内容的提问来源于stack exchange,提问作者osmangokalp
相关产品推荐
相关产品推荐

