[comp.lang.c] Oddities in ANSI 3rd review

am@cl.cam.ac.uk (Alan Mycroft) (08/02/88)

The following two points appear to be oddities in ANSI 3rd public review
spec.
1.  The function
        int f() { int x; char y; return sizeof(x)==sizeof(y); }
    seems required to return 1!!!!
    Reasoning: 3.2.1.1 says:
      "A char ... may be used in an expression wherever an int may be used ...
       the value is converted to an int."
    sizeof(.) is certainly a context in which an int may be used and
    so sizeof(<char variable>)==sizeof(int).
    Note that sizeof(char) probably differs from sizeof(<char variable>).
    I observe that the spec goes to some great trouble to specify
    where an array or function is converted to a pointer (3.2.2.1) whereas
    the notionally(?) identical contexts where char is converted to int
    suffers from sloppy drafting. (Convince me I'm wrong!)
2.  4.12.1:  "[In <time.h>] 'struct tm'  ... shall contain *at least*
     the following members... int tm_sec; ...".
    However, it would seem that an *implementation* would be non-conforming
    if it contained more members:  Suppose an implementer added a field
    'foo' (say) to struct tm.  Then the program
        #define foo @@@@@whizz!!!
        #include <time.h>
    would not compile (assuming <time.h> was textual).
    Hence the implementor can only add names in the reserved space of _A-Z or
    __A-Za-z0-9_.  This same remark obtains for views like:
>In <7351@cit-vax.Caltech.Edu> beckenba@cit-vax.UUCP (Joe Beckenbach) writes:
>>	Showing just the members seems to indicate to me that the members
>>listed are definitely there, but other members might be as well which
>>should really not be tampered with. This is simply information-hiding
>>which might be better done implemented in software than by lack of reference
>>in the documentation.

karl@haddock.ISC.COM (Karl Heuer) (08/04/88)

In article <253@gannet.cl.cam.ac.uk> am@cl.cam.ac.uk (Alan Mycroft) writes:
>2.  4.12.1:  "[In <time.h>] 'struct tm'  ... shall contain *at least*
>     the following members... int tm_sec; ...".
>    However, it would seem that an *implementation* would be non-conforming
>    if it contained more members: ...

Well, a conforming implementation could certainly add members in the reserved
namespace (leading underscore), and it could provide convenient access to them
via a macro "#define tm_usec __tm_extended_usec" which is only defined if the
user has enabled the extensions ("#include <extensions.h>" or whatever).  This
is the same sort of situation that the implementor must face when providing
non-ANSI functions like read().

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

guy@gorodish.Sun.COM (Guy Harris) (08/05/88)

> Well, a conforming implementation could certainly add members in the reserved
> namespace (leading underscore), and it could provide convenient access to
> them via a macro "#define tm_usec __tm_extended_usec" which is only defined
> if the user has enabled the extensions ("#include <extensions.h>" or
> whatever).

Or, alternatively, if your implementation has some way of distinguishing
"no-extensions" mode from "extensions" mode with some #ifdef at compile time,
you could do:

	struct tm {
		int	tm_sec;
		int	tm_min;
		int	tm_hour;
		int	tm_mday;
		int	tm_mon;
		int	tm_year;
		int	tm_wday;
		int	tm_yday;
		int	tm_isdst;
	#ifdef __EXTENSIONS__
		char	*tm_zone;
		long	tm_gmtoff;
	#else
		char	*__tm_filler_1;
		long	__tm_filler_2;
	#endif
	};

Unfortunately, there's no way to have unnamed fillers that aren't bit-fields,
so there's no way I can see of doing this without polluting your namespace with
ugly, although probably harmless "__tm_filler_N" names.  If you could do this,
I'd prefer it;

	struct tm {
		...
	#ifdef __EXTENSIONS__
		char	*tm_zone;
		long	tm_gmtoff;
	#else
		char	*;
		int;
	#endif
	};

anyone? :-)

guy@gorodish.Sun.COM (Guy Harris) (08/05/88)

> Unfortunately, there's no way to have unnamed fillers that aren't bit-fields,
> so there's no way I can see of doing this without polluting your namespace...

Make that "no clean, portable way I can see of doing this...".  Yes, you can,
in any given implementation, stick in an unnamed bit field that happens to be
the same size as the structure member that you're trying to render anonymous,
but you'd have to tweak the size of the bit field in different implementations.

karl@haddock.ISC.COM (Karl Heuer) (08/09/88)

[karl@haddock (Karl Heuer) writes that "#define tm_usec __tm_extended_usec" as
a conditionally defined macro would do the job]

[guy@gorodish.Sun.COM (Guy Harris) notes the alternative solution
	struct tm { ...
	#ifdef __EXTENSIONS__
		long	tm_usec;
	#else
		long	__tm_filler_1;
	#endif
	};
but says that this pollutes the namespace with "__tm_filler_N" names.]

Yes, but it's polluting the *implemention's* namespace, not the user's.  The
implementor need only check that the pattern "__tm_*" is not on the (finite)
list of patterns already in use by the implementation.  From the user's
viewpoint, this extension (either yours or mine) is harmless.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint