macro to specify output parameter

Guy Harris guy at sun.uucp
Fri Aug 22 05:44:56 AEST 1986

> > 	foo(c)
> > 		char &c;
> > 	{
> > 		...
> > 		c = 'a';	/* store 'a' in the "char" referred to by
> > 				   "c" */

> I don't like this.  It violates the nice consistent way that C expressions
> work.  'char *c' means that '*c' is of type char.  '&c' is not of type
> char in any other context.

Well, maybe a keyword like "ref" would have been preferable.  However, the
"syntax of declaration resembles syntax of use" rule of C may be consistent,
but also can be confusing, so I don't consider it particularly holy.

Also note that "&c" is not of type "char" in ANY context; inside the body of
"foo", "&c" is of type "pointer to char", since it takes the address of the
"char" referred to by "c".  (The code generated for that would almost
certainly just take the value of the pointer that implements "c" and use
it.)  Dereferencing of reference types is automatic, so "syntax of
declaration resembles syntax of use" doesn't apply here.

> I don't see any problem with using '*' instead of REF and DEREF.

Since reference types and pointer types have different semantics, there are
cases, at least in C++, where reference types are, I believe, necessary.
Also, there may be cases where writing code using reference types could
eliminated the possibility of aliasing and permit better optimization.

Also, pointer arguments are overloaded in C; they are used if you actually
want to pass a pointer to a routine (because the routine will actually be
modifying the pointer value, e.g. "strcpy", where the pointer merely
indicates the address of the *first* character to copy to and the *first*
location to copy it into), and also if you want to do "call-by-reference".
The presence of reference types makes it possible to state your intent more
directly in C++ than in C.

> In any case, either '*' or 'DEREF' is better than the foo example above
> since the uses of the output parameter are marked.

It's not clear that marking the *uses* is interesting.  Is one just trying
to find the places where the item pointed to by the argument is modified?
You might want to do that with objects other than formal parameters, so
using "*" or "DEREF" doesn't solve the entire problem.

One might want to mark the *definition* instead; if the object referred to
by the parameter is read-only, one obviously doesn't have to look for the
places it's modified.  This can be done with the "const" type modifier in
ANSI C and C++, both for pointer and reference types.  If the routine takes
a reference or pointer to something and *doesn't* modify that something, it
should be declared as taking "pointer to 'const' whatever" or "reference to
'const' whatever"; the compiler will refuse to compile any code that
attempts to modify that something.

> I would like to see variable size arrays allowed as local parameters.
> This would be a lot more efficient than using malloc().

I presume you mean "local variables", and not "local parameters"; you can
already handle variable-sized array parameters by the subterfuge of passing
a pointer to the array (or to its first member) along with its length (if
you *don't* pass the length, make sure you can't run off the end!).
Supporting variable-sized arrays, even just as local variables, adds some
complication to the compiler.  Consider a function with two such arrays.
The address of the second such array (or the first, depending on the order
in which they're allocated), is a variable.  This would most likely be
supported by computing the address at the time it's allocated, stuffing it
into an invisible local variable, and replacing references to the array with
dereferences of the pointer.

If you support them in structures, the complications get worse.

> I would like to "operator definition" which would allow you to opdef
> say '+' to cause it and its two arguments to be replaced by a macro
> called with the two arguments whenever the arguments are of a type
> specified in the definition.  This allows generalized treatment of
> operators on non-native types such as 'complex'.

Check out C++; you can do exactly that there.  You can overload existing C++
operators, binding them to functions.  You can then declare the function to
be "inline" so that the code is expanded in-line rather than producing a
function call.  In fact, one example Stroustrup gives is the addition of the
type "complex" to C++, without changing the compiler and without turning all
complex arithmetic operations into procedure calls.

> Perhaps new operators could be custom defined or the syntax (left/right
> association, priority) of existing operators changed (but probably not
> except for completeness, changing existing operators is a good way to
> make a program unreadable).

Probably not even for completeness; the added cost of complication in the
compiler doesn't seem worth it.  (Isn't there a minor industry producing
discussions of implementation of overloading in Ada compilers?)

> I would like to see "structure constants" which would allow assignment
> to aggregate types.

C++ has this, using "constructors".  Any "class", and structures are special
cases of classes, can have a "constructor" as a member function.  A
"constructor" can take arbitrary argument lists, and merely need construct
an object of the appropriate type.

I think if you declare the "constructor" as "inline", it will do the "right"
thing (i.e.,

	typedef class complex {
		double	real;
		double	imaginary;
		inline complex(double r, double i = 0) {
			real = r;
			imaginary = i;
	} complex;

will cause

	complex i = complex(1, 0);

to generate code like

	i.real = 0;
	i.imaginary = 1;

I don't know whether it can be set up to do this at compile time for static

> Macros would be nicer with "imbedded functions".
> #define	foo(x,y) { float a = 0.0; while (x) { a += y * x--; }; \
			   return a; }

See David Chase's recent posting; he proposes more-or-less the same sort of
thing, mentioning the similar sort of construct in BCPL.

Of course, for this sort of thing, C++ "inline" functions might be better.

Give a look at C++; don't let its syntax for reference types put you off.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy at (or guy at

More information about the Comp.lang.c mailing list