1

The fread(3) and fwrite(3) have an extra parameter for a variable number of items. So a typical write often has a hardcoded count when all it has is a char buffer to begin with e.g. fwrite(data, len, 1, stdout).

What is the point of this parameter? Was this always just a convenience "let the system do the multiplication" thing kind of like calloc(3) or did some historical operating systems and/or storage devices have special handling for individual items written?

Fueling my curiosity here is that I stumbled across some IBM z/OS documentation for their fwrite() which makes something of a distinction between "record I/O output" and "block I/O output" and talks about how each item could get truncated past a certain length — making me wonder if the item count parameter used to map to, say, separate physical punchcards — or at least maybe data could get written behind the scenes using ASCII "record separator" characters or whatever.

For contrast, the POSIX fwrite spec just outright says:

For each object, size calls shall be made to the fputc() function, taking the values (in order) from an array of unsigned char exactly overlaying the object.

Which invites the question of why fwrite didn't just take in a const uint8_t* buffer and an overall size_t total length in the first place like write(2) does.

4
  • I considered posting this to Retrocomputing.SE instead, but since at least in theory "questions about earlier versions of a current machine or OS" are still listed as off-topic there (retrocomputing.stackexchange.com/help/on-topic) it seemed reasonable to try here first. Personally [based on what gets discussed here vs. here in practice] I feel this would be a better fit over there and if any moderators here agree, feel free to migrate!
    – natevw
    Commented Oct 23, 2020 at 21:18
  • I think that this is perfectly on-topic, as stdio first appeared on Unix. But then I'm a policy-enforced, not a policy-enforcer here. Take my answer as a comment (which would've been, if the format of this site were less stupid and allowed for proper formatting in comments and proper discussion threads).
    – user313992
    Commented Oct 23, 2020 at 21:48
  • 2
    And by seeming coincidence, retrocomputing.stackexchange.com/q/16633/1932 . (-:
    – JdeBP
    Commented Oct 24, 2020 at 0:42
  • @JdeBP which doesn't have any real answer, either.
    – user313992
    Commented Oct 24, 2020 at 7:40

1 Answer 1

0

As far as I could gather, those functions first appeared in Unix version 7, and in that first implementation, only fwrite did something special: it checked the error flag of the stream after writing each size block of data, instead of checking the return value of putc, as fread did with getc. But it doesn't look like that had any practical effects, beside wasting some extra cycles in case of i/o error.

Since both putc and ferror were simple macros, I don't think that fwrite(b, large_val, 1, f) was much faster than fwrite(b, 1, large_val, f) even then.

fwrite(ptr, size, count, iop)
unsigned size, count;
register char *ptr;
register FILE *iop;
{
        register unsigned s;
        unsigned ndone;

        ndone = 0;
        if (size)
        for (; ndone<count; ndone++) {
                s = size;
                do {
                        putc(*ptr++, iop);
                } while (--s);
                if (ferror(iop))
                        break;
        }
        return(ndone);
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .