473,320 Members | 2,098 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Historical question, why fwrite and not binary specifier for fprintf?

In the beginning (Kernighan & Ritchie 1978) there was fprintf, and unix
write, but no fwrite. That is, no portable C method for writing binary
data, only system calls which were OS specific. At C89 fwrite/fread
were added to the C standard to allow portable binary IO to files. I
wonder though why the choice was made to extend the unix function
write() into a standard C function rather than to extend the existing
standard C function fprintf to allow binary operations?

Consider a bit of code like this (error checking and other details omitted):

int ival;
double dval;
char string[10]="not full\0\0";
FILE *fp;

fp = fopen("file.name","w");
(void) fprintf(fp,"%i%f%s",ival,dval,string);

It always seemed to me that the natural extension, if the data needed to
be written in binary, would have been either this (which would have
allowed type checking):

(void) fprintf(fp,"%bi%bf%bs",ival,dval,string);

or perhaps just this (which would not have allowed type checking):

(void) fprintf(fp,"%b%b%b",ival,dval,string);

(Clearly there are some issues in deciding whether to write for string
"not full", or the entire buffer, which could have been handled in the
%bs form using field width, for instance.)

Anyway, in the real world fwrite was chosen. For those of you who were
around for this decision, was extending fprintf considered instead of,
or in addition to fwrite? What was the deciding factor for fwrite?
I'm guessing that it was that everybody had been using write() for years
and it was thought that fwrite was a more natural extension, but that is
just a guess.

Thanks,

David Mathog
Nov 27 '07 #1
11 4239
David Mathog wrote:
In the beginning (Kernighan & Ritchie 1978) there was fprintf, and
unix write, but no fwrite. That is, no portable C method for writing
binary data, only system calls which were OS specific. At C89
fwrite/fread were added to the C standard to allow portable binary IO
to files. I wonder though why the choice was made to extend the unix
function write() into a standard C function rather than to extend the
existing standard C function fprintf to allow binary operations?
Perhaps because the UNIX functions were well known? Perhaps for reasons
of efficiency?
Consider a bit of code like this (error checking and other details
omitted):

int ival;
double dval;
char string[10]="not full\0\0";
FILE *fp;

fp = fopen("file.name","w");
(void) fprintf(fp,"%i%f%s",ival,dval,string);

It always seemed to me that the natural extension, if the data needed
to be written in binary, would have been either this (which would have
allowed type checking):

(void) fprintf(fp,"%bi%bf%bs",ival,dval,string);

or perhaps just this (which would not have allowed type checking):

(void) fprintf(fp,"%b%b%b",ival,dval,string);

(Clearly there are some issues in deciding whether to write for string
"not full", or the entire buffer, which could have been handled in the
%bs form using field width, for instance.)

Anyway, in the real world fwrite was chosen. For those of you who
were around for this decision, was extending fprintf considered
instead of, or in addition to fwrite? What was the deciding factor
for fwrite? I'm guessing that it was that everybody had been using
write() for years and it was thought that fwrite was a more natural
extension, but that is just a guess.
Personally I'm glad that direct I/O has separate functions for it. The
*printf()/*scanf() interface is already quite a complicated, bloated
one.

It seems to me that their primary use is when conversion is necessary.
Otherwise a more direct interface should be preferable, at least for
efficiency, if not for anything else.

Nov 27 '07 #2
David Mathog <ma****@caltech.eduwrites:
In the beginning (Kernighan & Ritchie 1978) there was fprintf, and
unix write, but no fwrite. That is, no portable C method for writing
binary data, only system calls which were OS specific. At C89
fwrite/fread
were added to the C standard to allow portable binary IO to files. I
wonder though why the choice was made to extend the unix function
write() into a standard C function rather than to extend the existing
standard C function fprintf to allow binary operations?

Consider a bit of code like this (error checking and other details omitted):

int ival;
double dval;
char string[10]="not full\0\0";
FILE *fp;

fp = fopen("file.name","w");
(void) fprintf(fp,"%i%f%s",ival,dval,string);

It always seemed to me that the natural extension, if the data needed
to be written in binary, would have been either this (which would have
allowed type checking):

(void) fprintf(fp,"%bi%bf%bs",ival,dval,string);

or perhaps just this (which would not have allowed type checking):

(void) fprintf(fp,"%b%b%b",ival,dval,string);
[...]

Neither form really allows type checking, unless the compiler chooses
(as gcc does, for example) to check the arguments against the format
string and issue warning for mismatches. Such checking is not
possible if the format string is not a string literal.

Your ``string'' argument is passed as a pointer to the first character
of the string (&string[0]). fprintf would have no way to know how
many characters to print -- unless it stops at the first '\0', but
that's likely to be inappropriate for a binary file.

The whole purpose of fprintf is to format data into text (the final
'f' stands for format). Binary output specifically doesn't do any
formatting; it just dumps the raw bytes. Having to invoke fprintf,
with all its internal machinery to parse the format string, when you
merely want to dump raw bytes doesn't seem like a good thing.

fwrite() does just what it needs to do, without all that conceptual
overhead.

Speaking of historical questions, were fread() and frwrite() invented
by the C89 committee, or were they based on existing practice? I
suspect the latter, but I'm not sure.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 27 '07 #3
In article <87************@kvetch.smov.org>,
Keith Thompson <ks***@mib.orgwrote:
>Speaking of historical questions, were fread() and frwrite() invented
by the C89 committee, or were they based on existing practice? I
suspect the latter, but I'm not sure.
They were existing practice.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 27 '07 #4
In article <fi**********@naig.caltech.edu>,
David Mathog <ma****@caltech.eduwrote:
>In the beginning (Kernighan & Ritchie 1978) there was fprintf, and unix
write, but no fwrite. That is, no portable C method for writing binary
data, only system calls which were OS specific. At C89 fwrite/fread
were added to the C standard to allow portable binary IO to files.
No. fwrite() and friends were present in the standard i/o library
introduced in 7th edition unix in 1979.
>I
wonder though why the choice was made to extend the unix function
write() into a standard C function rather than to extend the existing
standard C function fprintf to allow binary operations?
The standard i/o library provides two things: efficient buffering and
formatted i/o. getc(), fwrite(), etc provide buffering. printf() etc
provide formatting on top of that. It makes no sense for you to have
to use the formatting mechanism (and its overhead) just for buffered
i/o, whether text or binary.

The standard i/o library seems to me to be an excellent balance of
simplicity and functionality, unix and C at their best.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 27 '07 #5
Keith Thompson wrote:
David Mathog <ma****@caltech.eduwrites:
>In the beginning (Kernighan & Ritchie 1978) there was fprintf, and
unix write, but no fwrite. That is, no portable C method for writing
binary data, only system calls which were OS specific. At C89
fwrite/fread
were added to the C standard to allow portable binary IO to files. I
wonder though why the choice was made to extend the unix function
write() into a standard C function rather than to extend the existing
standard C function fprintf to allow binary operations?
[...]

...

Speaking of historical questions, were fread() and frwrite() invented
by the C89 committee, or were they based on existing practice? I
suspect the latter, but I'm not sure.
I believe they first appeared in public as part of the 7th Edition UNIX
standard library in January 1979.
Nov 28 '07 #6
Jack Klein wrote:
>
.... snip ...
>
*printf() and *scanf() are primarily designed to convert between
human readable text and binary format. Using them when you want
no such conversion does not even seem intuitive.
However, especially in the embedded field, they are often a
monstrous waste, and also an easy way to inject errors. Simple,
non-variadic functions to output a specific type with possibly a
field width specifier (see Pascal) are much more efficient.

The problem is that those functions, if linked, need to include all
the options, whether used or not. They are just too big and
all-encompassing. It makes much less difference on some OS where
the entire function is in one shared library file. But with static
linking the problem reappears everywhere.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 28 '07 #7
David Mathog wrote On 11/27/07 12:18,:
In the beginning (Kernighan & Ritchie 1978) there was fprintf, and unix
write, but no fwrite. That is, no portable C method for writing binary
data, only system calls which were OS specific.
There was putc(), which is portable. In fact, the
various Standards for C describe all the output operations
as operating "as if" by repeated putc() calls.
At C89 fwrite/fread
were added to the C standard to allow portable binary IO to files.
Although they are not mentioned in K&R, they are both
older than the ANSI Standard. ANSI did not "add" them; it
codified existing practice.
I
wonder though why the choice was made to extend the unix function
write() into a standard C function rather than to extend the existing
standard C function fprintf to allow binary operations?
... but fprintf() *can* generate binary output!

FILE *stream = fopen("data.bin", "wb");
double d = 3.14159;
char *p;
for (p = (char*)&d; p < (char*)(&d + 1); ++p)
fprintf (stream, "%c", *p);

(Error-checking omitted for brevity.) putc() would be
a better choice, but fprintf() *can* do it, if desired.
Consider a bit of code like this (error checking and other details omitted):

int ival;
double dval;
char string[10]="not full\0\0";
FILE *fp;

fp = fopen("file.name","w");
(void) fprintf(fp,"%i%f%s",ival,dval,string);

It always seemed to me that the natural extension, if the data needed to
be written in binary, would have been either this (which would have
allowed type checking):

(void) fprintf(fp,"%bi%bf%bs",ival,dval,string);
As Charlie Brown said, "Bleah!" Note that this would
offer no way to output a promotable type without performing
the promotion and a subsequent demotion (I'm not worried
about the speed, but about potential changes in the data,
things like a minus zero float losing its minus sign in
the conversion to double and back). Writing out a struct
would be clumsy in the extreme, as you'd need to enumerate
every element, one by one. I can't see any way to write
a bit-field with this scheme, nor any way to write a union
without foreknowledge of which element was current (short
of repeated "%c" as above -- which requires no extensions).
[...] For those of you who were
around for this decision, was extending fprintf considered instead of,
or in addition to fwrite? What was the deciding factor for fwrite?
I wasn't there and don't know, and the Rationale offers
no hints. But the idea of trying to use fprintf() for this
strikes me as tightening screws with hammers: It's the wrong
interface, that's all. Besides, fread() and fwrite() already
existed; they were not "creatures of the committee" in the
way that <stdlib.hwas, for example.

--
Er*********@sun.com

Nov 28 '07 #8
In article <1196265404.5351@news1nwk>,
Eric Sosman <Er*********@Sun.COMwrote:
>In the beginning (Kernighan & Ritchie 1978) there was fprintf, and unix
write, but no fwrite. That is, no portable C method for writing binary
data, only system calls which were OS specific.
There was putc(), which is portable.
To be pedantic, in 1978 there was indeed putc(), but it wasn't the
putc() we know today. The then-current sixth edition unix used a
pointer to a 518-byte "struct buf", which the programmer had to
create, instead of the opaque FILE struct introduced in seventh
edition (1979) along with most of the stdio functions we use today.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 28 '07 #9
Richard Tobin wrote On 11/28/07 13:00,:
In article <1196265404.5351@news1nwk>,
Eric Sosman <Er*********@Sun.COMwrote:

>>>In the beginning (Kernighan & Ritchie 1978) there was fprintf, and unix
write, but no fwrite. That is, no portable C method for writing binary
data, only system calls which were OS specific.

> There was putc(), which is portable.


To be pedantic, in 1978 there was indeed putc(), but it wasn't the
putc() we know today. The then-current sixth edition unix used a
pointer to a 518-byte "struct buf", which the programmer had to
create, instead of the opaque FILE struct introduced in seventh
edition (1979) along with most of the stdio functions we use today.
To be pedantic back at'cha: putc() and FILE and fopen()
and so on are described in Chapter 7 of "The C Programming
Language" by Brian W. Kernighan and Dennis M. Ritchie, ISBN
0-13-110163-3. The copyright date is 1978, not 1979 or later,
and the putc() description is on page 152.

Perhaps Unix lagged C by a year or so?

--
Er*********@sun.com
Nov 28 '07 #10
In article <1196277214.437935@news1nwk>,
Eric Sosman <Er*********@Sun.COMwrote:
To be pedantic back at'cha: putc() and FILE and fopen()
and so on are described in Chapter 7 of "The C Programming
Language" by Brian W. Kernighan and Dennis M. Ritchie, ISBN
0-13-110163-3. The copyright date is 1978, not 1979 or later,
and the putc() description is on page 152.

Perhaps Unix lagged C by a year or so?
I was relying on the date of the unix manuals. I don't think there
was anything except unix to run C on back then. Perhaps the updated
library was available was available before the new version of unix, or
perhaps the book was written before the corresponding software was
generally available. (I don't seem to have my K&R1 to hand to see if
it says anything about it.)

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 28 '07 #11
Richard Tobin wrote:
In article <1196277214.437935@news1nwk>,
Eric Sosman <Er*********@Sun.COMwrote:
> To be pedantic back at'cha: putc() and FILE and fopen()
and so on are described in Chapter 7 of "The C Programming
Language" by Brian W. Kernighan and Dennis M. Ritchie, ISBN
0-13-110163-3. The copyright date is 1978, not 1979 or later,
and the putc() description is on page 152.

Perhaps Unix lagged C by a year or so?

I was relying on the date of the unix manuals. I don't think there
was anything except unix to run C on back then. Perhaps the updated
library was available was available before the new version of unix, or
perhaps the book was written before the corresponding software was
generally available. (I don't seem to have my K&R1 to hand to see if
it says anything about it.)
UNIX v7 was released in January 1979; I guess that K&R1 was written
based on what was being put together for UNIX v7. Given the difference
between copyright and release dates, it's quite possible that UNIX v7
was finished within Bell Labs before K&R1 was finished.

UNIX v6 had primitive versions of putc() and fopen() which do not match
the definitions in K&R1 or UNIX v7. The Standard I/O library as we know
it today is based on that in UNIX v7 as described in K&R1.
Nov 29 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Jerald | last post by:
Hi. I'd like to know when python started working with bytecode. It seems natural that in the first python implementations code was really interpreted : executed directly. As a result, in the...
2
by: news.hku.hk | last post by:
i have a binary file "myfile.bin", its output of "od -t x1 myfile.bin" is: 0000000 7f 45 4c 46 01 02 01 and longer. i want the output to screen be: 7f 45 4c 46 01 02 01 i try to write the...
21
by: nephish | last post by:
i have an interesting project at work going on. here is the challenge. i am using the serial module to read data from a serial input. it comes in as a hex. i need to make it a binary and compare it...
1
by: sugaray | last post by:
1 / \ 2 3 / / \ 4 5 6 \ / \ 7 8 9 Given the binary trees above, determine the order in which the nodes will be visited in the mixed order given by invoking
6
by: Eddie | last post by:
Hi, Is it possible to make a program in VB.net that will convert letters, numbers etc to Binary Code? I have the tables here that show me exactly what each character works out to, but I was...
6
by: William J. Leary Jr. | last post by:
I've got a history question, and several of you seem familiar with the history of C, so perhaps someone knows. The following: #include<stdio.h> struct checkit { int a; int b; char c;
5
by: Bit byte | last post by:
If I write data from structures to a binary file in C#, can I read back the file using "unmanaged" C++ ?
2
by: Oriane | last post by:
Hi folks, what makes that the SOAP/Xml binary encoding is smaller than the "text" one ? Is is only because the XML tags are more or less suppressed ? More generally, I don't understand how...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.