[comp.sys.ibm.pc] Problems with understanding C

richardh@killer.UUCP (11/26/87)

In article <1203@lznv.ATT.COM>, psc@lznv.ATT.COM (Paul S. R. Chisholm) writes:
> <PS/2: yesterday's hardware today; OS/2: yesterday's software tomorrow>
> 
> In article <1610047@hpcvlo.HP.COM>, jason@hpcvlo.HP.COM (Jason Su) writes:
> > /* Here's another irritating bug that compiled(!) w/o errors on MSC 4.0. */
> > typedef int map;
> > 
> > typedef struct {
> > 	int *map;		/* <-- This is the error line */	
> > } my_struct;		
> 
> K&R, p. 200:  "Declarations whose 'storage class' is typedef do not
> define storage, but instead DEFINE IDENTIFIERS WHICH CAN BE USED LATER
> AS IF THEY WERE TYPE KEYWORDS . . ."  [emphasis mine]
> 
> The identifier "map" is effectively a reserved keyword from the time
> its typedef is complete through the end of the compiled module.  MSC
> 4.0 was incorrect in accepting this code in the first place.  I suspect
> that most C compilers that support typedef will reject it.
> 

The above code fragment compiles without error for a very good reason: 
there are no errors in it. 

There are, however, two errors of understanding in the above. 1) The use 
of a name in a typedef does not create a keyword any more than the 
declaration of a function or variable does. "As if" doesn't mean "is". 
The name is still free to be used in any other valid context. 2) There 
is no name conflict in the above. The first declaration using the name "map" 
causes the identifier to be placed in the name space associated with variables, 
functions, typedef names, and enumeration constants. The second causes the 
identifier "map" to be placed in the name space associated with component 
names. There is no conflict because the second name will always occur in a 
context involving selection (xxx.map or xxx->map).

Most modern C compilers recognize five distinct overloading classes (also
called name spaces): 1) preprocessor macro names; 2) statement labels;
3) structure, union, and enumeration tags; 4) component names; and
5) other names (variables, functions, typedef names, enumeration constants).

This can lead to such abominations as:

struct horrid {
	char *horrid_string;
	struct horrid *horrid;
} horrid;

Now *horrid.horrid is a struct horrid. Sorry that I can't get a label in 
there somewhere.

Don't take my word for it. Check Harbison and Steele p. 53, sec. 4.2.4 (1st 
ed.).

You folks need to understand C before you start saying a code fragment is 
right or wrong.

richard hargrove
...!killer!richardh
-------------------