drew@lethe.UUCP (Drew Sullivan) (04/26/89)
Under ANSI-C the I think that the following is legal: +------------------------------------------------------------ | #define foo_t unsigned int /* from include file 1 */ | extern foo_t foo(void); | | #define foo_t unsigned int /* from include file 2 */ | extern foo_t foo(void); +------------------------------------------------------------ But, is the following legal: +------------------------------------------------------------ | typedef unsigned int foo_t; /* from include file 1 */ | extern foo_t foo(void); | | typedef unsigned int foo_t; /* from include file 2 */ | extern foo_t foo(void); +------------------------------------------------------------ If it is not legal how do we guard the multiple typedefs. Do we use #ifdefs, and if so, are there to be any conventions. -- -- Drew Sullivan, <drew@lethe.uucp>
gwyn@smoke.BRL.MIL (Doug Gwyn) (04/29/89)
In article <2322@lethe.UUCP> drew@lethe.UUCP (Drew Sullivan) writes: >typedef unsigned int foo_t; /* from include file 1 */ >extern foo_t foo(void); >typedef unsigned int foo_t; /* from include file 2 */ >extern foo_t foo(void); No, the second typedef is syntactically invalid. The conventional way to guard against this is: #ifndef _FOO_T_DEFINED #define _FOO_T_DEFINED typedef unsigned int foo_t; #endif Sorry about that..
rex@aussie.UUCP (Rex Jaeschke) (04/30/89)
> From: gwyn@smoke.BRL.MIL (Doug Gwyn) > The conventional way to guard against this is: > #ifndef _FOO_T_DEFINED > #define _FOO_T_DEFINED > typedef unsigned int foo_t; > #endif Watch out though 'cos this is the solution for implementers. If you are Joe Shmoe programmer, you should avoid the leading underscores since implementers are permitted to use those names in their headers. Rex ---------------------------------------------------------------------------- Rex Jaeschke | C Users Journal | Journal of C Language Translation (703) 860-0091 | DEC PROFESSIONAL |1810 Michael Faraday Drive, Suite 101 uunet!aussie!rex | Programmers Journal | Reston, Virginia 22090, USA ----------------------------------------------------------------------------
dave@lethe.UUCP (Dave Collier-Brown) (04/30/89)
In article <2322@lethe.UUCP> drew@lethe.UUCP (Drew Sullivan) writes: | typedef unsigned int foo_t; /* from include file 1 */ | extern foo_t foo(void); | typedef unsigned int foo_t; /* from include file 2 */ | extern foo_t foo(void); In article <10167@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: | No, the second typedef is syntactically invalid. | The conventional way to guard against this is: | #ifndef _FOO_T_DEFINED | #define _FOO_T_DEFINED ... It is interesting that one has to use ifdefs to protect a redefinition of a typedef but not of a macro. In P.J. Plauger's column on Standard C [1] he comments.. The committee eventually permitted one form of refefinition, however. Plum insisted we allow "benign" redefinition of a macro. Loosely speaking, a macro definition is benign if it results in essentially the same definition as before. Permitting benign redefinition, Plum argues, greately simplifiees writing the same definition in multiple #include files. (The Standard C library has multiple definitions of the macro NULL, for instance.) Is there a technical reason for the difference in redefinition rules for macros -vs- typedefs, or is it present for administrative or historical reasons? Or is it an error? --dave c-b ps: the above is something close to the meaning of Drew's initial question. -- David Collier-Brown, | {toronto area...}lethe!dave 72 Abitibi Ave., | Joyce C-B: Willowdale, Ontario, | He's so smart he's dumb. CANADA. 223-8968 |
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/01/89)
In article <16.UUL1.3#5077@aussie.UUCP> rex@aussie.UUCP (Rex Jaeschke) writes: >Watch out though 'cos this is the solution for implementers. Yeah, I debated with myself whether or not to put in the leading _ and decided that if I didn't somebody (you, I suppose) would post a follow-up warning that implementers would need to use an _. Sigh.
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/02/89)
In article <2402@lethe.UUCP> dave@lethe.UUCP (Dave Collier-Brown) writes: > Is there a technical reason for the difference in redefinition rules >for macros -vs- typedefs, ...? Yes. Oh, you want to know what it is? Well, consider how the compiler is going to parse a complex declaration containing several typedefs. How does it know whether you are defining the same typedef a second time or are just using it to help typedef something else? There's no analogous problem with #define, due to its unambiguous syntax that makes it clear what identifier is being defined.
suitti@haddock.ima.isc.com (Stephen Uitti) (05/03/89)
In article <10190@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <2402@lethe.UUCP> dave@lethe.UUCP (Dave Collier-Brown) writes: >> Is there a technical reason for the difference in redefinition rules >>for macros -vs- typedefs, ...? > >Yes. We're waiting... holding our collective breath. > >Oh, you want to know what it is? Well, consider how the compiler is >going to parse a complex declaration containing several typedefs. >How does it know whether you are defining the same typedef a second >time or are just using it to help typedef something else? > >There's no analogous problem with #define, due to its unambiguous >syntax that makes it clear what identifier is being defined. This is the first good answer i've heard. I still think it is a (design) bug, though not by any means a new one. Four design options come to mind: 1. Omit typedef from the language. People will then not be tempted to use it. 2. iftypedef(x), untypedef(x), and possibly retypedef(x, y). Example: iftypedef(mode_t) { untypedef(mode_t); retypedef(mode_t, (char *)); } 3. Disallow typedef definitions using typedef'ed symbols. Allow typedef foo int; typedef foo int; to work. 4. Disallow typedef foo *foo; that is, self-referential typedefs. Then allow typedef foo int; typedef foo int; to work, or even typedef u_int unsigned int; typedef foo unsigned int; typedef foo u_int; /* synonym - it is the same */ to work. Option 1) is what my choice would have been at the dawn of time (which is sometime before i knew any C). Typedef functionality can be obtained with #defines. Of course, enums would also be gone, replaced by #defines. Option 2) is a hack on a kludge. In particular it makes typedef stuff look executable. Option 3) doesn't support "complex declarations". Be real. Typedefs are nuisance synonyms that seldom have real use (the UN*X kernel is one of those "seldom" places - nothing i've ever written outside the kernel would benefit by them. The kernel uses them for simple types for portability reasons - not for itself, but for its clients). Option 4) doesn't actually sound too bad. It is probably provably completely backwards compatible. Stephen. ...And my spelling checker agrees, it said "No errors!".
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/03/89)
In article <12937@haddock.ima.isc.com> suitti@haddock.ima.isc.com (Stephen Uitti) writes: >Option 1) is what my choice would have been at the dawn of time >(which is sometime before i knew any C). Typedef functionality >can be obtained with #defines. Only in simple cases. In complicated situations, typedefs are practically essential. None of your four options (plus other suggestions X3J11 considered) struck me as feasible. Nice try but no cigar.
karl@haddock.ima.isc.com (Karl Heuer) (05/04/89)
In article <10190@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <2402@lethe.UUCP> dave@lethe.UUCP (Dave Collier-Brown) writes: >>[why are repeated typedefs illegal?] > >Well, consider how the compiler is going to parse a complex declaration >containing several typedefs. How does it know whether you are defining the >same typedef a second time or are just using it to help typedef something >else? It seems to me that the compiler is going to have to be able to handle such a case anyway. Note that typedef int foo; void f(void) { typedef int foo; } *is* legal (and would be even if the two types didn't match; the second simply hides the first until end-of-scope). At the point of the second declaration, the compiler has to be prepared for both a redeclaration of foo and a new declaration using foo. Given a compiler that can parse this, it would seem that the extra effort to handle the desired feature would be negligible. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
corbett@beatnix.UUCP (Bob Corbett) (05/06/89)
In article <12955@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
!It seems to me that the compiler is going to have to be able to handle such a
!case anyway. Note that
! typedef int foo;
! void f(void) {
! typedef int foo;
! }
!*is* legal (and would be even if the two types didn't match; the second simply
!hides the first until end-of-scope).
The latest draft of the standard I have (December 7, 1988) does not allow a
storage-class-specifier (in this case typedef) in a struct-declaration-list.
If X3J11 added this feature since that draft, we need another round of public
review.
!Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
Faithfully yours,
Bob Corbett
diamond@diamond.csl.sony.junet (Norman Diamond) (05/08/89)
In article <12937@haddock.ima.isc.com> suitti@haddock.ima.isc.com (Stephen Uitti) writes: >Four design options come to mind: >1. Omit typedef from the language. People will then not be tempted to > use it. >Option 1) is what my choice would have been at the dawn of time >(which is sometime before i knew any C). Typedef functionality >can be obtained with #defines. Of course, enums would also be >gone, replaced by #defines. Option 1) was in fact the case at the dawn of time. The C community discovered that this was one of the things that Pascal did right, and it was copied (clumsily) into C. >2. iftypedef(x), untypedef(x), and possibly retypedef(x, y). Example: > iftypedef(mode_t) { > untypedef(mode_t); > retypedef(mode_t, (char *)); > } >Option 2) is a hack on a kludge. In particular it makes typedef stuff >look executable. That's exactly true. These kinds of operations are expected more at the preprocessing stage. If you can design some preprocessing directives that would handle this problem correctly and not be too difficult to implement, you might get it into C-0X (the next standard after C-89). >3. Disallow typedef definitions using typedef'ed symbols. Allow > typedef foo int; > typedef foo int; > to work. >Option 3) doesn't support "complex declarations". typedef definitions using typedef'ed symbols really are important. Anyway, gcc does allow duplicate typedefs if they match (warning about shadows instead of giving an error). So complex declarations can still be permitted, and shadows can still be allowed. Any vendor who has trouble with these could perhaps distribute gcc instead of their own C compiler. >4. Disallow > typedef foo *foo; > that is, self-referential typedefs. Huh? typedef foo *foo; is already illegal. It is self-contradictory, not just self-referential. >Then allow > typedef foo int; > typedef foo int; > to work, as in Option 3) above > or even > typedef u_int unsigned int; > typedef foo unsigned int; > typedef foo u_int; /* synonym - it is the same */ > to work. unsigned unsigned x; does not become a valid declaration, no matter what you do with typedefs (though it was legal in K&R, again no matter what you do with typedefs). What happens next: typedef signed foo int; is this equivalent to typedef signed unsigned int int; >Be real. That's good advice. Take it! >Typedefs are nuisance synonyms that seldom have real use This is completely false. >(the UN*X kernel is one of those "seldom" places It is one of those "many" places. >- nothing i've ever written outside the kernel would benefit by them. So _you_ haven't done any real programming outside the kernel. Big deal. -- Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.co.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?