not really Re: Style guides and portability

Stephen Clamage steve at taumet.com
Fri Jan 18 04:15:48 AEST 1991


dkeisen at Gang-of-Four.Stanford.EDU (Dave Eisen) writes:

>>In article <10608 at hydra.Helsinki.FI>, Lars Wirzenius asks:
>>>Is there any problem in using 
>>>	printf("%ld", (long) bigint)
>>>other than that it's clumsy?
>It sorta defeats the purpose, doesn't it? 
>The point of using a type like int32 is to avoid hardcoding the 
>current compiler's idea of what a long looks like into the code and
>here you are using "lf" and "long" thousands of times all over your
>code. If you wanted to go this route, maybe something like 
>#define BIGINT_FORMAT  "ld"
>#define BIGINT_TYPE     long
>would be appropriate.

The source of the problem is inherent in printf-like functions, where
the receiving function does not know the type of the parameter being
passed, and has to be told in an auxiliary parameter (the format string).
Whenever you have the same piece of information kept in two places you
have synchronization problems -- in this case the type of the parameter
being passed is known by the compiler at the calling location, and has
to be duplicated by the programmer independently.

Other languages have solved this problem in different ways -- none of
them by using a printf-like function.

In Pascal, I/O is built into the language, so you can say
	write('the value is ', x);
which works no matter what the numeric type of x.  This solution is
not available in C.

In Modula-2, there is a separate output function for each data type.
This solution can be used in C, and with prototyping the compiler
will convert the numeric argument to the right type, or warn you
about dangerous conversions:
	int i;
	long l;
	void printi(int);
	void printl(long);
	printl(i);	/* i will be automatically converted to a long */
	printi(l);	/* compiler should warn about truncating l */

In C++, you can take advantage of function overloading to declare
multiple versions of a function with different parameter types, and
the compiler will call the right one:
	int i;
	long l;
	void print(int);
	void print(long);
	print(i);	// print(int) is called
	print(l);	// print(long) is called
You can also use one of the standard stream I/O packages, in which the <<
operator is overloaded for output and can be chained:
	#include <stream.h>	// or <iostream.h>
	int i;
	long l;
	cout << "the value is " << i;	// cout is standard output
	cout << "the value is " << l;

The key to minimizing porting difficulties is to avoid the inherent
problem in printf by one of the above solutions.  I find them cleaner
than
	printf(BIGINT_FORMAT, (BIGINT_TYPE) bigint);
-- 

Steve Clamage, TauMetric Corp, steve at taumet.com



More information about the Comp.lang.c mailing list