Path: utzoo!attcan!uunet!munnari.oz.au!bruce!cechew From: cechew@bruce.cs.monash.OZ.AU (Earl Chew) Newsgroups: comp.lang.c Subject: Re: problem with fread/fwrite Keywords: fread, fwrite, file pointers Message-ID: <3337@bruce.cs.monash.OZ.AU> Date: 13 Nov 90 00:56:01 GMT References: <402@bally.Bally.COM> <14384@smoke.brl.mil> <13992@ulysses.att.com> <2677@cirrusl.UUCP> Organization: Monash Uni. Computer Science, Australia Lines: 75 In <2677@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes: >In <13992@ulysses.att.com> kpv@ulysses.att.com (Phong Vo[drew]) writes: > The standard, in this case, basically just documents the behavior of > stdio without considering that this is a bad design that arose from > a bad implementation. It is ugly to have to call fseek before > switching modes. I think that this is true. >I believe the requirement to call fseek (etc.) when switching arises >out of the need to make stdio fast. Due to buffering, alternating This is not the case. The main obstacle to switching between reads and writes is: 1. the behaviour of early implementations of stdio 2. subsequent casting of (1) in concrete by ANSI-C There is a need to make stdio fast --- but this does not prohibit arbitrary switching between read and write modes. Most implementations of stdio buffer data between calls to read(2) and write(2). Thus the cost of making a system call is only incurred every BUFSIZ bytes. Intermediate data is transferred directly to the buffer. The main impediment to switching modes in many implementations of stdio is the use of a single buffer pointer (usually _ptr). This single pointer functions as a read pointer when reading and a write pointer when writing, allowing quick access to the buffer. Calls to a buffer fill or flush function are only made when the pointer reaches some high water mark. Thus (getc(fp); putc(0, fp)) or (putc(0, fp); getc(fp)), especially when the pointer is in the middle of the buffer. It is possible to perform an automatic mode switch if *two* pointers are used: a reading pointer and a writing pointer. >reads and writes can confuse each other. The only way the stdio >library could automatically protect you against this would be for it to >explicitly test for internal state before every read and write. E.g., >within fread, we sould have: > if (my_state == DOING_WRITE) { > .. resync buffer .. > my_state = DOING_READ; > .. rest of fread .. > } Some implementations of stdio do this anyway to prevent users from hanging themselves: if (my_state == DOING_WRITE) { ... error ... } ... rest of fread ... In these cases, there already is a guard on the fread() code, so replacing `... error ...' with `... resync buffer ...' is possible without loss in performance for the normal case. I am unsure whether ANSI-C prohibits stdio implementations from automatic switching, but it clear that if such a feature were to be implemented, its use would make the application non-conforming. In any event, use of the separate read and write pointers allows runtime checking to ensure that an explicit switch is made between read and write modes, even if automatic switching is not implemented (ie it is possible to trap {getc(fp); putc(0, fp);} or {putc(0, fp); getc(fp);}). Earl -- Earl Chew, Dept of Computer Science, Monash University, Australia 3168 EMAIL: cechew@bruce.cs.monash.edu.au PHONE: 03 5655447 FAX: 03 5655146 ----------------------------------------------------------------------