But it's clearer to write
FILE* log = fopen(...);
write_log_header (log);
fclose (log);
That's a good example. In effect, the function is a wrapper around
fopen().
Where do you find that style? Certainly not in K&R.
If you absolutely insist on having strict pairings of
functions for allocation and deallocation, you could write
FILE *open_log(int i);
int close_log(FILE *log);
but close_log would do exactly the same thing as fclose().
The point of open_log and close_log is that they refer to a 'log
device' which needs not be a file. When you use FILE* in the interface
you cannot change the log destination without breaking user code. You
probably also use a write_log function (instead of fwrite) which
prepends the log enty with a timestamp, line number, ...
In general, some functions allocate resources, and other functions
deallocate those same resources. Having a strict one-to-one mapping
between the two can be helpful, I suppose, but IMHO it's not strictly
necessary.
It's not necessary but it helps you create large-scale applications.
It's an important idiom to keep track of the resources in a C program.
Even the standard memory allocation functions don't do
this; malloc() and calloc() both allocate memory, free() deallocates
it, and realloc() potentially does both. The clean symmetry of
fopen() and fclose() is broken by freopen().
Not by freopen() which just associates the existing stream with a new
file.
Programmers simply have to *read the documentation* to find out which
function does what.
Yes, always, but that's not the point here.
The interface described by the documentation
should be as simple as possible, but no simpler. If it makes sense to
have a strict pairing of allocators and deallocators, by all means do
that; if it doesn't, don't.
Programming in any language becomes manageable only when people adhere
to certain styles and idioms. If you merely knew the language syntax
you would know handly anything of a language. IMO, it's important to
propagate idioms that 'work' and warn of those that don't.
(In OO terms, there's no requirement to have exactly one constructor
and exactly one destructor for a given type.)
I don't see a problem in more than one open/create/init function per
'object', e.g. open_log1(), open_log2(), ...
Best regards,
Roland Pibinger