home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!microsoft!hexnut!jimad
- From: jimad@microsoft.com (Jim Adcock)
- Subject: Re: Standard library functions and macros
- Message-ID: <1992Dec29.222453.7209@microsoft.com>
- Date: 29 Dec 92 22:24:53 GMT
- Organization: Microsoft Corporation
- References: <BzFM01.CD@frumious.uucp> <1992Dec23.214139.24948@microsoft.com> <DAVEG.92Dec24193847@synaptx.synaptics.com>
- Lines: 202
-
- In article <DAVEG.92Dec24193847@synaptx.synaptics.com> daveg@synaptics.com (Dave Gillespie) writes:
- |In article <1992Dec23.214139.24948@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
- |I have to disagree here. Usually when language standards talk about
- |the "meaning" of a program, they are referring only to whether or not
- |it is correct, and what its behavior will be if it is correct. As I
- |understand it, all the talk about macros in the C standard is there
- |purely to reserve to implementors the right to provide fast macro
- |implementations of library functions.
-
- Again, section 4.1.6 of X3.159-1989 calls out explicit rights not
- only of implementors, but also of programmers. Implementors have
- the right to use macro implementations, but also have to provide
- function implementations "in the background." Programmers have the
- right to bypass the macro implementation [if any] using the "background"
- function-call implementation. The ANSI-C++ committee intends to
- usurp both the rights of the implementor and the rights of the
- programmer on this matter. Why? There is NO REASON why the ANSI-C++
- committee has to use the ANSI-C libraries if they don't like the ANSI-C
- library rules. Let the ANSI-C++ committee define their own libraries,
- with the own *differently named include headers*, if they do not like
- the way the ANSI-C libraries are defined to work. That way the
- programmer could choose whose set of rules they agreed with --
- ANSI-C or ANSI-C++ -- and more importantly existing historical
- agreements between C implementors and C programmers would not be broken.
-
- For example, the ANSI-C++ committee could decide they know better than
- ANSI-C how the ANSI-C headers ought to work, could name THEIR version
- of the header files <stdio.h++> [or something] and then the programmer
- could decide WHOSE header and set of rules to follow <stdio.h> or
- <stdio.h++>
-
- I am not saying this is what SHOULD be done, I'm just saying there
- is no excuse for the ANSI-C++ committee to REQUIRE changes to the
- rules of how the ANSI-C libraries and their associated headers work.
- Because ANSI-C++ could simply NAME their headers differently if they
- are going to require that their headers WORK differently!
-
- |If the only effect of `#undef putchar' is to change whether or not
- |a fast macro or a slow equivalent function is used, i.e., if it only
- |affects performance and not results, then I'd say it's improper for
- |a standard to legislate it one way or another, or for a portable
- |program to depend on it.
-
- I agree. Thus I am lobbying against the proposed ANSI-C++ mandated
- change. If the ANSI-C++ doesn't mandate the implementation, then
- implementors can *continue* to implement standard C functions using
- macros. Portable programs [ie "strictly conforming"] won't depend on this.
- But non-portable but still conforming programs CAN and DO depend upon
- this. Remember, the vast majority of programs ARE NOT written to
- be portable, and it was never the intent of ANSI-C to *require*
- portability, but rather to *allow* portability to people who were
- so motivated. On the contrary, ANSI-C clearly states that they
- consider *speed* a more important criteria than portability, and
- that programmers should not be hindered from writing fast, non-portable,
- programs. Requiring inline implementation would be such a hindrance, because
- the reality remains that in some instances macros can still be
- faster than inlines.
-
- |Even if `putchar' were a function instead of a macro, don't compilers
- |sometimes inline-expand functions anyway? A good optimizing compiler
- |ought to be able to do this, whether or not there are "inline"
- |declarations in the language. As far as I know, there is no way in
- |C to require that a function be compiled out-of-line. The only
- |language I can think of offhand that does provide for this is Common
- |Lisp.
-
- Various implementation have many different capabilities and implementations.
- What I am lobbying against is the proposed ANSI-C++ change requiring
- implementors NOT to use one historical implementation choice, namely
- the new proposed restriction requiring implementations to no longer
- use macro implementations of historical C standard functions. Even
- though those macro implementations are clearly permitted and intended as
- stated in the ANSI-C standard.
-
- |I don't have a copy of the standard handy, but my K&R II uses language
- |like "if it is a macro" in its description of "putchar". Doesn't that
- |imply that it is perfectly legal for a compiler to implement `putchar'
- |as a function, not a macro?
-
- Yes, and it implies that it is perfectly legal for a compiler to
- implement it as a macro, not a function. And it is perfectly legal
- for a conforming program to expect its given implementation to provide
- this function in macro form, and to require that particular implementation
- for the "success" of that particular program. Strictly-conforming
- programs are not allowed to have expectations on implementation beyond
- that called out in ANSI-C. Conforming programs can have any expectations
- on a particular implementation that they want. Such expectation represent
- private agreement between an implementor and a programmer using that
- implementation. Now ANSI-C++ would override such private agreements.
-
- |In fact, is there anything preventing a C implementation from putting
- |
- | static int putchar(int c) { return putc(c, stdout); }
- |
- |in its <stdio.h> header? Is there anything preventing a compiler
- |from expanding a call to "putchar" inline, given this definition?
- |(Urgh, I wish I had a copy of the standard around...)
-
- Again, it is not an issue of "preventing" it is an issue of "requiring" --
- the proposed ANSI-C++ changes would require changes to existing
- implementations, breaking the agreements already established between
- that implementation and the expectations of conforming programs for
- that implementation.
-
- |> Also, note that a conforming C implementation of these standard library
- |> functions using macros can accept a superset of the parm types that a
- |> C++ extern implementation or inline implementation can accept.
- |
- |Well, yes, but can a conforming, i.e., portable program depend on this?
-
- You confuse conforming with strictly conforming. A conforming program
- CAN make such expectations. A strictly-conforming program cannot.
- Conforming and strictly conforming programs are BOTH "legal" programs.
- Neither is a "bad" program. They might just meet differing requirements.
- For example, it is not uncommon for otherwise strictly-conforming
- programs to contain conforming sections surrounded by #ifdefs for
- various target implementations, such that the ultimate in performance
- can be achieved on each of those implementations. This is "good".
- The programmer took such effort because such effort was needed.
- Such effort should be respected. There should not be new requirements
- added in the name of "portability" that now defeats such efforts.
-
- |My K&R says `int putchar(int c)'. I have to assume that this is what
- |I have when I write a call to `putchar'. Even if I have a whiz-bang
- |extended C compiler that allows me to pass other things to `putchar',
- |I have to assume any code that uses this will break when I move to
- |another compiler, be it a C++ compiler or just another vendor's C.
-
- Yes. Such a program would be conforming not strictly conforming.
- Again, there is nothing 'wrong' with conforming programs, they are
- just not very portable. It was the expressed intent of C to allow
- BOTH programs that are not portable, and programs that ARE portable,
- the difference being in the effort and desires of the program writer.
- Frequently portability comes at an expense of speed, for example,
- or at the expense of writing [and generating] more code.
-
- |> Thus, requiring that a macro *not* be
- |> used for implementation requires that some possible conforming programs
- |> will no longer be accepted.
- |
- |As I understand it, even if it's required for `putchar' and to `putc'
- |to be macros, it is still legal for their definitions to be
- |
- | #define putc(c,f) fputc(c,f)
- | #define putchar(c) putc(c,stdout)
- |
- |which means that a conforming program couldn't possibly pass anything
- |to `putchar' which it couldn't also pass to `fputc', which is certainly
- |allowed to be a function.
-
- No. Again you confuse conforming with strictly conforming. What
- you say above is true of strictly conforming programs, not of conforming
- programs.
-
- |What other properties of `putchar' being a macro or not could a
- |conforming program depend on?
- |
- |> The other side of the coin is that it then becomes impossible for
- |> programmers to specify *whether or not* they want an inline implementation,
- |> which is a stated intent of the original ANSI-C standard library
- |> macro/function implementations.
- |
- |Could you please provide a quotation?
-
- Again, section 4.1.6 of X3.159-1989
-
- A tiny subpart says:
-
- "Any macro definition of a function can be suppressed LOCALLY by
- enclosing the name of the function in parentheses, ...."
-
- [emphasis mine]
-
- Clearly the intent is that the programmer can CHOOSE where and when
- to use the macro implementation [fast speed] and where and when
- to use the function implementations [small size] and the programmer
- can mix and match these choices as the *programmer* so desires.
-
- Please read the whole paragraph if this remains unclear to anyone.
-
- |> So then the next person has to somehow magically discover that the "meaning"
- |> of these "standard" functions have been changed from the C++ standard have
- |> been changed from the C standard....
- |
- |What has actually changed, that this next maintainer could perceive?
-
- Speed verses size tradeoffs have been removed from the intended control
- of both the programmer and the implementor. Thus the next maintainer says
- "Gosh darn, recompiling this under C++ made it 20% bigger and 2X as slow --
- clearly C++ s*cks the big one. What do I do now?"
-
- |Okay, the performance has changed some, but performance can change even
- |when you install a new rev of the "same" compiler.
-
- But typically implementors are not REQUIRED to make their next generation
- compiler generate bigger slower code. Customers do complain, and rightly
- so, when a next generation compiler does worse on their programs than
- their previous compiler. The ANSI-C++ committee would now so require.
- I believe this would be a bad decision for C++. What would happen is
- that C programs would simply continue to be maintained as C programs,
- and would not be ported over to C++. Because who wants bigger slower code?
-
-