[comp.lang.c] Why are typedef names in the same name space as variable names?

jgm@spice.cs.cmu.edu (John Myers) (11/14/86)

Keywords:


In article <4220@ut-ngp.UUCP> dlnash@ut-ngp.UUCP (Donald L. Nash) writes:
>Why are typedef names in the same name space as variable names?...

If they weren't, then what would the output of the following program be?

#include <stdio.h>
main()
{
    typedef car foo;
    long foo;
    
    printf("%d\n",sizeof(foo));
}

ballou@brahms (Kenneth R. Ballou) (11/16/86)

In article <1092@spice.cs.cmu.edu> jgm@spice.cs.cmu.edu (John Myers) writes:
>In article <4220@ut-ngp.UUCP> dlnash@ut-ngp.UUCP (Donald L. Nash) writes:
>>Why are typedef names in the same name space as variable names?...
>
>If they weren't, then what would the output of the following program be?
>
>#include <stdio.h>
>main()
>{
>    typedef car foo;
Is this a typo, and supposed to be typedef char foo ?
>    long foo;
>    
>    printf("%d\n",sizeof(foo));
>}

I don't see that there is a question here.  Sizeof is *NOT* a function, as was
quite thoroughly discussed some time back in this group.  Note that (foo) in
this case is the syntax of a type cast, and in this case, sizeof returns 
the size of a datum of type foo (in this case, 1).  If, however, you were to
write  sizeof foo , you would then get the size of a long integer on your
machine.  References:  K&R:  page 126 (explains sizeof (object) and also
points out that sizes are given in unspecified units called "bytes," which
are the same size as a char); page 187 (gives two forms of the *operator*
sizeof, namely  sizeof expression  and  sizeof (type-name) ); page 188 (defines
the meaning of the constructs involving sizeof and also notes that "byte"
is the space required to hold a char *in all existing implementations*).

--------
Kenneth R. Ballou		...!ucbvax!brahms!ballou
Department of Mathematics	ballou@brahms.berkeley.edu
University of California
Berkeley, California  94720

greg@utcsri.UUCP (Gregory Smith) (11/16/86)

allou@brahms (Kenneth R. Ballou) writes:
>jgm@spice.cs.cmu.edu (John Myers) writes:
>>dlnash@ut-ngp.UUCP (Donald L. Nash) writes:
>>>Why are typedef names in the same name space as variable names?...
>>
>>If they weren't, then what would the output of the following program be?
>>
>>#include <stdio.h>
>>main()
>>{
>>    typedef char foo;
>>    long foo;
>>    
>>    printf("%d\n",sizeof(foo));
>>}
>
>I don't see that there is a question here.  Sizeof is *NOT* a function, as was
>quite thoroughly discussed some time back in this group.  Note that (foo) in
>this case is the syntax of a type cast, and in this case, sizeof returns 
	and also the syntax of a long expression.
>the size of a datum of type foo (in this case, 1).  If, however, you were to
>write  sizeof foo , you would then get the size of a long integer on your
>machine.  References:  K&R:  page 126 (explains sizeof (object) and also
>points out that sizes are given in unspecified units called "bytes," which
>are the same size as a char); page 187 (gives two forms of the *operator*
>sizeof, namely  sizeof expression  and  sizeof (type-name) ); page 188 (defines
>the meaning of the constructs involving sizeof and also notes that "byte"
>is the space required to hold a char *in all existing implementations*).
>
Objection sustained. If this were the only problem with putting typedefs
and variable names in separate spaces, then it would be probably be resolved
as you said in the given case. However, it ain't.

Having written a C parser, I can testify that it is imperative that the
two be in the same space. It must be possible to distinguish the end of
declarations at the start of a block. The last declaration ( if any )
is not delimited in any way - the parser must be able to determine that
the next 'thing' is a statement and not a declaration. Since
declarations are structured completely differently from statements, it
really helps if the distinction can be made very early ( i.e. after
looking at one token ).

typedef char foo1;
int foo2();
char *abc;
d(){
	foo1 (*xyz);	/* declare xyz as pointer to char */
	foo2 (*abc);	/* call foo2 with *abc as parameter */
	...
}
So if you allow typedefs and variables to be in separate spaces, and
change foo1 and foo2 to foo, how do tell whether foo(*abc) is a declaration
or a statement?
Less extreme examples can be constructed:
int foo3;  ... foo1 * xyz; This is also legal, but doesn't do anything.
Now, change foo1,foo3 to 'foo'. You can't expect the *parser* to
look at the construction "foo * xyz;" and think 'well that would be silly if
foo was an int, so it must be a typedef'.

"It is agreed that the ice is thin here."	- K&R, pg 206

-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

wohler@sri-spam.istc.sri.com (Bill Wohler) (11/18/86)

In article <2183@sdcsvax.UCSD.EDU> bruss@sdcsvax.UUCP (Brian Russ) writes:
>	If [typedefs and variables] weren't in the same name space,
>	you could, in addition to the above, write:
>
>	struct foo { /* ... */ };
>
>	foo foo;
>
>	Yuch!  Do you really want/need this flexibility?  In my opinion,
>it's better the way it is now.

  i haven't thought of an example which would necessitate having
  typedefs and variables in the same name space.  it is very common
  to have:

struct foo {...};
...
struct foo foo;

  thinking of different names for the structure and the variable
  becomes difficult when we just hack and don't expand our
  vocabulary reading faulkner or didion. ;-)

						--bw

tim@ism780c.UUCP (Tim Smith) (11/21/86)

There is already a problem with telling when the declarations end.
Consider this program:

	main() {
		a;      /* declare an integer variable */
		a = 1;  /* put something in it */
	}

Every C compiler I have tried complains about an undeclared variable on
line 2.  If "a" is a global, they have no problem:

	a;
	main() {
		a = 1;
	}
-- 
emordnilapanalpanama

Tim Smith       USENET: sdcrdcf!ism780c!tim   Compuserve: 72257,3706
                Delphi or GEnie: mnementh

jsdy@hadron.UUCP (Joseph S. D. Yao) (11/24/86)

In article <307@cartan.Berkeley.EDU> ballou@brahms (Kenneth R. Ballou) writes:
>In article <1092@spice.cs.cmu.edu> jgm@spice.cs.cmu.edu (John Myers) writes:
>>In article <4220@ut-ngp.UUCP> dlnash@ut-ngp.UUCP (Donald L. Nash) writes:
>>>Why are typedef names in the same name space as variable names?...
>>#include <stdio.h>
>>main()
>>{
>>    typedef car foo;
>>    long foo;
>>    printf("%d\n",sizeof(foo));
>>}
>I don't see that there is a question here.  Sizeof is *NOT* a function, as was
>quite thoroughly discussed some time back in this group.  Note that (foo) in
>this case is the syntax of a type cast, and in this case, sizeof returns 
>the size of a datum of type foo (in this case, 1).

(foo) is also an expression.  If the typedef were not present, this
would still be a legal C program, with an unambiguous compilation:
the size of the long int "foo" would be printed out.  As it is, I
believe either interpretation is "correct".

Thus, purely BTW, this can be considered a bad program -- I think
it's not a good idea to use a name for more than one purpose, when
a less ambiguous way of doing the same thing can be found.

As I mentioned before, to keep people honest and as MY OWN PERSONAL
preference of style, I use the parentheses in both cases.  (Emphasis
mine, not zippy's or root boy's -- don't flame if it's just not your
own personal style.)
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
			jsdy@hadron.COM (not yet domainised)

greg@utcsri.UUCP (Gregory Smith) (11/26/86)

In article <4647@ism780c.UUCP> tim@ism780c.UUCP (Tim Smith) writes:
>There is already a problem with telling when the declarations end.
>Consider this program:
>
>	main() {
>		a;      /* declare an integer variable */
>		a = 1;  /* put something in it */
>	}
>
>Every C compiler I have tried complains about an undeclared variable on
>line 2.  If "a" is a global, they have no problem:
>
>	a;
>	main() {
>		a = 1;
>	}
In the first example, line 2, 'a;' is a statement, to wit, the
expression 'a'.  It is an error only because there is no 'a' in scope.
Declarations inside blocks must specify a type or a storage class.  I
am not saying that this is perfectly consistent; however it is
thoroughly documented. In fact any C compiler that doesn't complain
about the first example must be broken in a nasty way.  Given this
rule, there is no ambiguity in determining whether a thing in a block
is another declaration or the first statement. If it starts with a
type/storage-class specifier keyword, it is a declaration. If it starts
with a currently defined typedef identifier, it is also a declaration.
Anything else is either a statement or a syntax error.

Do you expect to be able to declare the external function foobar
as below?

func(){
	foobar();		/* declare ext. function foobar */
	foobar();		/* call it */
}

-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

tim@ism780c.UUCP (Tim Smith) (12/02/86)

In article <3692@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes:
>>There is already a problem with telling when the declarations end.
>>Consider this program:
>>
>>	main() {
>>		a;      /* declare an integer variable */
>>		a = 1;  /* put something in it */
>>	}
>>
>In the first example, line 2, 'a;' is a statement, to wit, the
>expression 'a'.  It is an error only because there is no 'a' in scope.
>Declarations inside blocks must specify a type or a storage class.  I
>am not saying that this is perfectly consistent; however it is
>thoroughly documented.

Where is this documented?  K&R say that the type may be left out of
declarations ( giving "int" as the default ).  And they mention a
problem explicitly with typedefs.  I don't see anywhere that says I
must specify a type in other cases ( on the other hand, I haven't looked
very hard.  I may have missed it. ).

-- 
emordnilapregnolanalpanama

Tim Smith       USENET: sdcrdcf!ism780c!tim   Compuserve: 72257,3706
                Delphi or GEnie: mnementh

pdg@ihdev.UUCP (P. D. Guthrie) (12/03/86)

In article <4743@ism780c.UUCP> tim@ism780c.UUCP (Tim Smith) writes:
>Where is this documented?  K&R say that the type may be left out of
>declarations ( giving "int" as the default ).  And they mention a
>problem explicitly with typedefs.  I don't see anywhere that says I
>must specify a type in other cases ( on the other hand, I haven't looked
>very hard.  I may have missed it. ).

Well, I don't see them coming right out and saying it, but it is
strongly implied in the text and enforced in the grammar.
The exceptions are  when you have a storage class identifier (eg
register) or when it is an arg to a function (it defaults to int).

Something interesting that is in the text though is the way that the
default sc-specifiers are assigned.  K&R state that the default is auto
inside a function and *extern* outside.  It seems to be *static* in most
C implementations these days.

-- 

Paul Guthrie					We come in peace,
ihnp4!ihdev!pdg					We bring BEER!

greg@utcsri.UUCP (Gregory Smith) (12/04/86)

In article <4743@ism780c.UUCP> tim@ism780c.UUCP (Tim Smith) writes:
>>Declarations inside blocks must specify a type or a storage class.  I
>>am not saying that this is perfectly consistent; however it is
>>thoroughly documented.
>
>Where is this documented?  K&R say that the type may be left out of
>declarations ( giving "int" as the default ).  And they mention a
>problem explicitly with typedefs.  I don't see anywhere that says I
>must specify a type in other cases ( on the other hand, I haven't looked
>very hard.  I may have missed it. ).

Well, I take this back. Can't find it in K&R anywhere. It should
be mentioned on page 201 in 9.2, especially. It *has* to be a rule,
since there are umpteem valid declarations that become valid statements
when you don't give a storage class or type:
	int i=1;
	extern foo();
etc.

-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

henry@utzoo.UUCP (Henry Spencer) (12/04/86)

> ...default sc-specifiers are assigned.  K&R state that the default is auto
> inside a function and *extern* outside.  It seems to be *static* in most
> C implementations these days.

Can you name a few?  Extern is the way it has always been in C; compilers
which default to static are broken.  (Please don't cite C++, that isn't C.)
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry

bs@alice.UUCP (12/05/86)

In article <7374@utzoo.UUCP>, henry@utzoo.UUCP writes:
> > ...default sc-specifiers are assigned.  K&R state that the default is auto
> > inside a function and *extern* outside.  It seems to be *static* in most
> > C implementations these days.
> 
> Can you name a few?  Extern is the way it has always been in C; compilers
> which default to static are broken.  (Please don't cite C++, that isn't C.)
> -- 
> 				Henry Spencer @ U of Toronto Zoology
> 				{allegra,ihnp4,decvax,pyramid}!utzoo!henry

Most (all?) C compilers and lint will accept the following program:

file1:

	typedef int I;
	I i = 1;

file2:
	typedef char* I;
	I p = "asdf";

Is it legal? Personally, I think not because the name I which is external by
default has two definitions (but the C++ compiler also accepts it).

The default storage class specifiers are identical in C and C++ so the glib
remark about C++ is irellevant in the context. What is different about C++
in this context is that structure tags are in the same name space as
identifiers (including typedef names). For example, the following is not C++:

	struct s { int a; };
	struct s s;

As it happens, the generally available C++ implementation accepts this as an
aid to people mixing C and C++.

On a more general note what does it take for a C-like language/implementation
to be ``not C''?

For example, is the C-like language used on many UNIX systems ``not C'' for
failing accept this (perfectly legal) C program?:

	typedef double T;

	f() {
		typedef int T;
	}

(C++ accepts it, but on many systems its ``code generator'', cc, chokes on its
perfectly legal intermediate C).

C++ is C by the simple test of its compiler accepting a larger subset of what
is accepted to be C than most C compilers.

Is a ``C-like language'' with a keyword like ``near'' ``not C''? The compiler
for such a C-like language does not accept the perfectly legal C program:

	main() { int near = 2; printf("%n\n",near); }

Is a ``C-like language'' without the keyword ``enum'' C?

Clearly, any C with an extension that renders even a single legal C program
uncompilable is in a real sense ``not C''. One purpose of the ANSI C effort
is to define a minimum standard for what should be called C, but is the
minimum all that matters? If so, ought the ANSI C commitee abandon the
different standards found in the proposal (I think their names are:
``conforming'', ``strictly conforming'', `hosted'', and ``embedded''
implementations - each in a real sense defines a different language)?

I don't think so (this would imply 7 character names and several other horrors
- including having to change just about every large C program written to date
because of use of features not in ``strictly conforming ANSI C''). I don't
think that any member of the ANSI C comitte wants to have ONLY a minimal
standard and thereby stop further evolution of C. Hence the practical, but
rather ad hoc, acceptance of unspecified extensions in (mearly) conforming
implementations of C.

C++ is not strictly conforming ANSI C (as proposed), but it is C. The problem
is that it is also much more. In particular, being able to write things like

	class complex {
		double re, im;
	public:
		complex(double r, double i)
			{ re=r; im=i; }
		friend complex operator+(complex a, complex b)
			{ return  complex(a.re+b.re, a.im+b.im); }
	};

	f()
	{
		complex a = complex(1,2);
		complex b = a+complex(3,4);
	}

precludes writing things like

	main() { int class = 2; printf("%n\n",class); }

and

	struct complex { double re, im; };

	struct complex complex;
	complex.re = 2;

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

In article <6430@alice.uUCp> bs@alice.UUCP writes:
>file1:
>	typedef int I;
>	I i = 1;
>file2:
>	typedef char* I;
>	I p = "asdf";
>Is it legal? Personally, I think not because the name I which is external by
>default has two definitions (but the C++ compiler also accepts it).

I see no more reason to consider the abbreviation `I' external than
to do so for `COUNTER' in the following scenario:
file1:
	#define COUNTER int
	COUNTER i = 1;
file2:
	#define COUNTER long
	COUNTER l = 0;
It appears to depend on whether one considers typedef to be a convenient
shorthand or something more fundamental.  If you adopt your view, then
one needs to allow declarations such as:
	static typedef int I;

henry@utzoo.UUCP (Henry Spencer) (12/10/86)

> > Can you name a few?  Extern is the way it has always been in C; compilers
> > which default to static are broken.  (Please don't cite C++, that isn't C.)
> 
> The default storage class specifiers are identical in C and C++ so the glib
> remark about C++ is irellevant in the context...

Some private correspondence with Bjarne has cleared up a misunderstanding
on my part.  I was misled by (a) some confusing differences in terminology
between C and the C++ book, and (b) the fact that early, pre-book, versions
of C++ did indeed default to "static" (in the C meaning).  Bjarne comments:
"This was probably the right decision in the abstract, but in actual use it
created so much resistance and confusion that I backed off."
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry

jsdy@hadron.UUCP (Joseph S. D. Yao) (12/15/86)

In article <4647@ism780c.UUCP> tim@ism780c.UUCP (Tim Smith) writes:
>	main() { a; a = 1; }
>Every C compiler I have tried complains about an undeclared variable on
>line 2.  If "a" is a global, they have no problem:
>	a; main() { a = 1; }

This is an illegal declaration, anyway.  Declarations must contain
at least one "storage class" specifier or one "type" specifier.  A
compiler that accepts the above is exhibiting a bug, not a feature.

*** Stamp out programs that put arbitrary decrees on text shape ***
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
			jsdy@hadron.COM (not yet domainised)