[mod.std.c] Standard C Digest - V1 #4

osd7@homxa.UUCP (Orlando Sotomayor-Diaz) (12/15/84)

ANSI Draft of Proposed  C Language Std.

Mail your replies to the author(s) below or to cbosgd!std-c.
Cbosgd is reachable via most of the USENET nodes, including ihnp4,
ucbvax, decvax, hou3c....  Administrivia should be mailed to 
cbosgd!std-c-request.

ARPA -> mail to cbosgd!std-c@BERKELEY.ARPA

**************** mod.std.c  Vol. 1 No. 4  12/15/84 ********************

Today's Topics:

	Comments on Sections A and B of 11/12/84 Draft (X3J11/84-161)
	Comments on Section C of 11/12/84 Draft (X3J11/84-161)
	Comments on Section D of 11/12/84 Draft (X3J11/84-161)

----------------------------------------------------------------------

Date: Tue, 11 Dec 84 20:51:22 EST
From: ihnp4!seismo!elsie!ado
Subject: Comments on Sections A and B

*	In section A.7 (page 3) appears:

		Strictly conforming programs are intended to be maximally
		portable.

	Given that the draft standard extends the C language (with a unary plus
	operator, a "case" statement allowing for a range of cases, and in other
	ways) it's possible to write strictly conforming programs that cannot
	be compiled by any existing C compiler that I know of.  I be reluctant
	to call such programs "maximally portable."  I suggest deleting this
	sentence from the draft standard.

*	In section B.3.2 (page 9) appears:

		\a  (alert) Produces an implementation-defined audible or
		    visible representation of an alert character.  Any
		    consequent alteration to the printing position is
		    implementation-defined.

	First, I favor changing the second sentence to read "The printing
	position remains as is."  Doing this would eliminate the need for
	programs using the alert character to do repositioning after writing
	the character; given the usual mapping of the alert character to a bell,
	this also accurately describes what happens.

	Second, I favor using

		\!

	or some other escape sequence involving a non alphanumeric character to
	represent the alert character.  This helps matters if a program is
	compiled on an "old" system--for example, on our 4.1bsd system, the
	program
		main(){printf("\aHello\n");}
	produces the message
		aHello
	while the program
		main(){printf("\!Hello\n");}
	produces the message
		!Hello
	...and I suggest that it's easier to diagnose what's going on in the
	second case than it is in the first.
	(If '\a' was selected because it is already used to represent the alert
	character in some systems, by all means stick with it.)

	And if the standard is going to add in new escape sequences, perhaps
	the committee will want to consider resurrecting the old (if I remember
	alright) '\s' sequence that stood for a space character--perhaps
	transmogrifying it to '\_' in the process.

*	In section B.3.4.1 (page 10) on the <limits.h> file appears:

		When these constraints may be expressed numerically, they
		are available via the standard header <limits.h>.

	I suggest changing this to

		Some of these constraints are available via the standard
		header <limits.h>.

	to avoid controversy over what may and may not be expressed numerically.

*	In section B.3.4.1 (page 10) appears:

		* maximum exponent power of ten that floating point can
		  represent	38

	On our 4.1bsd system, the program:
		main() { printf("%f\n", 10.0e37);printf("%f\n", 10.0e38); }
	produces this output:
		100000000000000000000000000000000000000.000000
		170141183460469230000000000000000000000.000000
	which means (to me) that 37 is the maximum "power of ten" that floating
	point can represent.  Either I or the description can stand being made
	clearer.

	I also wonder if 38 is the right value to have for a "strictly
	conforming" implementation.  Perhaps a lower value would allow more
	implementations to be conforming while at the same time not breaking
	any existing software.

*	In section B.3.4.1 (page 10) appears:

		* maximum number of bits for smallest datum (char or byte) [ 8 ]

	Later, in section C.1.2.5 (page 16) appears:

		An object declared as a character (char) is large enough to
		store any member of the execution character set that can be
		specified as a single-character character constant without
		using an octal or hexadecimal escape sequence.

	Since this second requirement might be satisfied (given the number of
	members of the execution character set) by as few as seven bits, I
	suggest changing the 8 to a seven in section B.3.4.1.

*	In section B.3.4.2 (page 11) appears:

		* External identifiers beginning with a leading underscore, and
		  all identifiers beginning with two underscores, are reserved
		  for use by the implementation and must not be used by a
		  program, except to specify implementation-defined values.

	This seems rather one-sided.  I suggest adding:

		* External identifiers that do not begin with an underscore are
		  reserved for use by programs and must not be used by the
		  implementation, except to specify implementation-defined
		  values.

	or some variant.

----------------------------------------------------------------------

Date: Tue, 11 Dec 84 20:51:22 EST
From: ihnp4!seismo!elsie!ado
Subject: Comments on Section C

*	In section C.1.2.1 (page 15) appears:

		If the declaration appears within the list of parameters in
		a function prototype, the identifier has function prototype
		scope, which extends from the completion of the declaration of
		the parameter to the end of the declaration of the function.

	I suggest replacing "to the end of the declaration of the function"
	with "to the end of the function prototype."

*	In section C.1.7 (page 22) appears:

		The contents of a comment are examined only to find the
		characters */ that terminate it.  Thus comments do not nest.

	Later, in section E.3 (page 130) appears:

		An implementation may generate warnings. . .The following are
		a few of the more common situations.

		* The characters /* are found in a comment (SC.1.7).

	The first statement that comments are examined ONLY to find */ seems
	at odds with the second that a warning may be issued if /* is found in
	a comment.  I suggest changing the first statement to read:

		Comments do not nest.

*	In section C.3.1.2 (page 28) appears:

		A function call is a primary expression followed by
		parentheses. . .The primary expression must have type "function
		returning type" or "pointer to function returning type". . .

	I guess that this statement is designed to avoid breaking programs
	like:
		subr()
		{
		}
		main()
		{
			int (*	ptr)();
			subr();
			(*subr)();
			ptr();
			(*ptr)();
		}
	where, because of laxness on the part of some existing compilers,
	source code that in some sense "isn't right" nonetheless compiles.
	However, I note that a program like:
		subr()
		{
		}
		main()
		{
			int (*	ptr)();
			subr();
			(*subr)();
			(**subr)();
			ptr();
			(*ptr)();
			(**ptr)();
		}
	also compiles.

	If the goal is to avoid breaking existing programs regardless of how
	silly they may be, I suggest changing the cited passage to:
		A function call is a primary expression followed by
		parentheses. . .The primary expression must have type "function
		returning type" or "pointer to function returning type" or
		"pointer to pointer to function returning type" (and so on). . .

	If the goal is to have a reasonable standard, I suggest changing the
	cited passage to:

		A function all is a primary expression followed by
		parentheses. . .The primary expression must have type "function
		returning type". . .

*	In Section C.3.1.3 (page 29) appears:

		One special guarantee is made. . .If a union contains several
		structures that share a common initial sequence, and if the
		union object currently contains one of these structures, it is
		permitted to inspect the common initial part of any of them.

	    Examples. . .

		The following is a valid fragment:

			union {
				struct {
					int	type;
				};
				struct {
					int	type;
					int	intnode;
				} ni;
				struct {
					int	type;
					float	floatnode;
				} nf;
			} u;
			...
			u.nf.type = 1;
			u.nf.floatnode = 3.14;
			...
			if (u.n.type == 1)
				... sin(u.nf.floatnode) ...

	Valid, yes. . .and granted, it is used for the purposes of an example.
	Still, why would the above code be used rather than:

			struct {
				int	type;
				union {
					int	intnode;
					float	floatnode;
				} u;
			} s;
			...
			s.type = 1;
			s.u.floatnode = 3.14;
			...
			if (s.type == 1)
				... sin(s.u.floatnode) ...

	Since the example in question is designed to legitimize the cumbersome
	"special guarantee" that precedes it, I like to see a more legitimate
	example.

*	Section C.3.3.3 describes a "unary + operator."  I suggest dropping
	this from the standard. . .it adds no functionality, and use of it by
	programs will ensure that they won't be portable to existing systems.

*	Section C.5.2 describes "type specifiers," with the type specifier
	"const" among them.  I recall the (perhaps apocryphal) story of Dennis
	Ritchie being asked what Dennis would do differently if "reinventing"
	UNIX (AT&T Bell Laboratories trademark).  Dennis's alleged response was
	that the only change would be to use "create" instead of "creat" as the
	name of the relevant system call.

	With that in mind, I suggest changing the keyword to "constant."
	(Either that or change "volatile" to "volat." :-))

*	In section C.5.3.3 (page 47) (on function declarators) appears:

		Any identifier declared in the list has function prototype
		scope, which extends to the end of the declaration of the
		function.

	I suggest replacing "to the end of the declaration of the function"
	with "to the end of the function prototype."

*	In Section C.7.1 (page 57) appears:

		Any formal parameter that is not declared or whose type is not
		given is taken to have type signed int.

	Oh the lint grief that this might cause!  I suggest replacing
	"signed int" with "int."

*	In Section C.8 (page 59) (on preprocessing directives) appears:
	
		. . .directives. . ."begin with" a # separator character;
		more precisely, by a # token that is the first character in the
		source file (after any number of spaces and horizontal-tab
		characters) or that follow a new-line character (after any
		number of space and horizontal-tab characters).

	The exclusion of form-feed characters and vertical-tab characters from
	the set of characters that may appear before the '#' makes skipping of
	"white space" in preprocessors more difficult.  I suggest replacing
	"any number of spaces and horizontal-tab characters" with "any amount
	of white space" in the above passage.

*	In Section C.8.3 (page 81) appears:

		# if	constant-expression	new-line

	I'm unclear on whether floating point constant expressions are allowed
	here.  I like the standard to be clear on that.

----------------------------------------------------------------------

Date: Tue, 11 Dec 84 20:51:22 EST
From: ihnp4!seismo!elsie!ado
Subject: Comments on Section D

*	Section D.9.5.3 (page 89) describes the "mode" arguments to "fopen,"
	among them:

		"rb+"	open binary file for update (reading and writing)
		"wb+"	create binary file for update or truncate
		"ab+"	append; open binary file or create for update,
			writing at end-of-file.

	I suggest changing these to "r+b", "w+b", and "a+b", respectively.
	Doing this allows programs using such modes to be ported without
	change to existing Berkeley systems.

*	Sections D.9.10.2 and D.9.10.3 describe the feof and ferror
	functions, which are specified with these prototypes on page 101:

		int feof(FILE *stream);
		int ferror(FILE *stream);

	It may be possible to change these prototypes to:

		int feof(const FILE *stream);
		int ferror(const FILE *stream);

	It may even be desirable.
--------------------------------------
End of Vol. 1, No. 4. Std-C  (Dec. 15, 1984  14:00:00)
-- 
Orlando Sotomayor-Diaz/AT&T Bell Laboratories/201-870-7249
		      /Crawfords Crnr. Rd., Holmdel WB 3D109, NJ, 07733
UUCP: {ihnp4, houxm, akgua, mhuxd, ...}!homxa!osd7