[comp.lang.c] More ANSI comment help wanted: #define void int vs. #define void char

ado@elsie.UUCP (Arthur David Olson) (06/06/88)

Here's another "help wanted on a comment to X3J11" request.  One of the
comments I sent in during the second public review period ran along these lines:

	Rationale, Sectioin 3.8.3, Page 64

	Description:
		Contains a sample keyword redefinition:
			#define void int
		along with a note that "The redefinitions of void and const
		could be useful in retrofitting more modern C code to an older
		implementation."

		Since the Standard requires a void * to have the same
		representation as a char *, and since a char * may not have the
		same representation as an int *, this definition seems
		suboptimal.

	Proposed Change:
		Change the above line to read
			#define void char

The response I received (was marked "Not an official X3J11 document"),
said that while "#define void char" might be better when it comes to pointers,
there were other cases where "#define void int" was better.  Can anyone give a
concrete example?
-- 
		Market swaps ends for Chinese native.  (5)
	ado@ncifcrf.gov			ADO is a trademark of Ampex.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/06/88)

In article <8085@elsie.UUCP> ado@elsie.UUCP (Arthur David Olson) writes:
>The response I received (was marked "Not an official X3J11 document"),
>said that while "#define void char" might be better when it comes to pointers,
>there were other cases where "#define void int" was better.  Can anyone give a
>concrete example?

There have been compilers that either did not know about "void" at all,
or that had various breakages involving e.g. pointers to functions
returning void (some of the Berkeley compilers had that problem).

Thus, when compiling code such as
	void func() { extern void exit(); /* ... */ }
it has often been useful to do the equivalent of "cc -Dvoid=int file.c".
Using char instead of int would not only gain nothing, but it would
introduce possible error (since in such an implementation, exit() would
probably be defaulted to return int).  Until recently, there has not been
code containing void *, but there has been lots of code like the above
example.

lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani) (06/06/88)

In article <8085@elsie.UUCP> ado@elsie.UUCP (Arthur David Olson) writes:
	...
>The response I received (was marked "Not an official X3J11 document"),
>said that while "#define void char" might be better when it comes to pointers,
>there were other cases where "#define void int" was better.  Can anyone give a
>concrete example?

	void blob() { ... }

would become:

	int blob() { ... }

instead of:

	char blob() { ... }

Old C libraries commonly don't list the function return type to indicate a
void but it really means int.  The #define would retain compatibility with
the old libraries.  Anyone got better examples?

-- 
Larry Cipriani, AT&T Network Systems and Ohio State University
Domain: lvc@tut.cis.ohio-state.edu
Path: ...!cbosgd!osu-cis!tut.cis.ohio-state.edu!lvc (strange but true)

ado@elsie.UUCP (Arthur David Olson) (06/06/88)

< < The response I received (was marked "Not an official X3J11 document"),
< < said that while "#define void char" might be better when it comes to
< < pointers, there were other cases where "#define void int" was better.
< < Can anyone give a concrete example?
< 
< . . .when compiling code such as
< 	void func() { extern void exit(); /* ... */ }
< . . .[u]sing char instead of int would not only gain nothing, but it would
< introduce possible error (since in such an implementation, exit() would
< probably be defaulted to return int).

If someone could explain the error possibly being introduced here,
I'd appreciate it.
-- 
		Market swaps ends for Chinese native.  (5)
	ado@ncifcrf.gov			ADO is a trademark of Ampex.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/07/88)

In article <8087@elsie.UUCP> ado@elsie.UUCP (Arthur David Olson) writes:
>If someone could explain the error possibly being introduced here,
>I'd appreciate it.

"extern char exit();" is plain wrong on EVERYbody's system.  Whether
or not this causes a problem depends on the implementation.
If a header is included that has e.g. "extern exit();" in it
then there is a type clash, too.

I just spent a whole (long) day hand-editing some C++ output C code
sent to me from a system that had globally mapped "void" to "char".
This was not a lot of fun, because some of the "char"s were correct
and some weren't.  In fact, most of them weren't.  I had to study the
context of each "char" to determine what to do.  (I turned most of
them back into "void" since the only problem with my compiler was
lack of support for "void *".)

ado@elsie.UUCP (Arthur David Olson) (06/09/88)

> "extern char exit();" is plain wrong on EVERYbody's system.  Whether
> or not this causes a problem depends on the implementation.
> If a header is included that has e.g. "extern exit();" in it
> then there is a type clash, too.

Thanks for the posting; these points should definitely help in improving my
comment.  Let's see if I can get some more help.

Consider this code:
	-------------------------
	extern void * malloc();
	char *
	getten()
	{
		return malloc(10);
	}
	--------------------------
where this dumb function just returns a point to ten character's worth of
allocated storage.  Now if we
	#define void int
as the standard suggests for backporting purposes, "old" compilers will happily
compile the code without complaint--and on systems where (int *) != (char *),
all hell will mysteriously break loose at runtime.

In this case, if we
	#define void char
the problem is avoided.

So:  are there any instances where a
	#define void char
will introduce runtime problems (that is, cause "quiet changes")
rather than causing compile-time problems ("noisy changes")?
(Again, I'm interested in concrete examples.)
-- 
		Grocery swaps ends for Chinese native.  (5)
	ado@ncifcrf.gov			ADO is a trademark of Ampex.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/11/88)

I think this is a nonissue on which too much effort is being expended.
The original example (#define void int) is just an illustration of why
it MIGHT under SOME circumstances be USEFUL to be permitted to use
#define to redefine keywords.  NO redefinition of "void" is UNIVERSALLY
proper.

To take a specific case:  Although I did not draft the part about
"#define void int", my applications are prepared to do just that when
the (non-ANSI) C compilation environment warrants, as it does on older
4BSD systems and on some microcomputer C implementations (those that
do not provide the "void" extension to K&R [1st Edition] C).  The
specific mechanism I use is to include, in virtually EVERY application,
a private header <std.h> that I set up once for each compilation
environment.  This defines a bunch of stuff the implementation of which
varies from system to system but the use of which remains the same.
Here is an extract of relevant portions of one implementation of <std.h>:

typedef char	*pointer;		/* generic pointer (void *) */

#define	const		/* nothing */	/* (undefine for ANSI C) */

/* ANSI C definitions */

#ifndef EXIT_SUCCESS
#define	EXIT_SUCCESS	0
#endif
#ifndef EXIT_FAILURE
#define	EXIT_FAILURE	1
#endif

/* other kludges for deficient C implementations etc.: */
/*#define	strchr	index		/* 7th Edition UNIX, 4.2BSD */
/*#define	strrchr	rindex		/* 7th Edition UNIX, 4.2BSD */
/*#define	void	int		/* K&R 1st Edition followers */

Notice the last line.  I came up with this well before X3J11, and I
have seen other programmers do the same.  Notice also that my
applications NEVER contain the "void *" that you worry about being
broken by "#define void int"; instead I always use the generic
"pointer" type for such pointers, and define it appropriately in
this header.

So in my situation, "#define void int" is sometimes useful, but
"#define void char" never is (and can be harmful).  There is
certainly no need to change the X3J11 example.