Path: utzoo!mnetor!uunet!lll-winken!lll-tis!ames!mailrus!tut.cis.ohio-state.edu!rutgers!bellcore!faline!thumper!ulysses!andante!alice!dmr From: dmr@alice.UUCP Newsgroups: comp.lang.c Subject: volatile isn't necessary, but it's there Message-ID: <7794@alice.UUCP> Date: 6 Apr 88 05:40:36 GMT Organization: AT&T Bell Laboratories, Murray Hill NJ Lines: 87 Since a good many messages have ardently defended the 'volatile' type qualfier, it might be worth pointing out a few things. Most important, the notion is not, so far as I know, under serious attack in X3J11; there is every reason to believe it will be in ANSI C. In my noalias diatribe I took a passing swipe at it (a position I will defend below), but on the whole, I am willing to leave volatile alone and concentrate on getting rid of noalias. Volatile is of use only with optimizing compilers; those that don't do some kind of data-flow analysis can ignore it. More bluntly, it is intended to be used in cases where your compiler will do something other than what your program plainly asks it to do. People seem to be thinking of three categories of use. 1) Accessing memory-mapped device registers 2) Special cases involving automatic variables in a routine that calls setjmp 3) Shared memory, and also interrupt routines. The X3J11 documents (the dpANS itself and the Rationale) specifically mention the first two, but carefully avoid talking about the third. I have no real gripe about the first; I just think it is unnecessary. It seems just as reasonable for purveyors of optimizing compilers for machines with memory-mapped IO to have a compiler flag that says "please be cautious about cacheing things in this routine." Alternatively, they could accept a #pragma in the code. It is true that putting volatile in the language encourages everyone to do the job in the same way, but it is by no means clear that, on balance, `volatile' makes C a better language. There is a real cost in having the feature in the language. It is just one more peculiar thing to learn and be confused about. If there is one thing I have learned from reading this newsgroup, and other popular reactions to C, it is that people have trouble understanding the language. Features that do nothing but request a compiler not to compile your program incorrectly are not really what C needs. (I'm especially amused by some of the more extreme positions stated in favor of `volatile.' May I be permitted to assert that it is possible to write a successful operating system without `volatile,' even on machines with memory-mapped IO?) I am much more worried about the second justification. It simply caters to broken compilers. Because some machines find it hard to handle setjmp/longjmp properly, X3J11 ruled that "[following a longjmp], [a]ll accessible objects have values as of the time longjmp was called, except that the values of objects of automatic storage duration that do not have volatile type and have been changed between the setjmp invocation and longjmp call are indeterminate." The Rationale is fairly explicit about the apologia. This is just a botch; the committee should have insisted that, if necessary, the compiler recognize setjmp and handle its caller specially. They edged around this anyway; what other use is the insistence that setjmp be a macro? (A footnote in the Rationale poses this question, too.) The third hope for volatile, namely shared memory, is in some ways the most interesting because it nibbles at the edge of mechanisms that will become more important in the future. Nevertheless, as several have pointed out, the Standard conspicuously avoids the extensions needed to make shared memory work (e.g. semaphores). The dpANS even says, "what constitutes an access to an object that has volatile-qualified type is implementation-defined," and the sections that discuss what volatile actually does mean are correspondingly inexplicit. If you hope to find in the Standard that "extern volatile mutex; ++mutex" has an iron-clad meaning, you'll be disappointed. Thus, using volatile for shared memory may be syntactically portable, but it is not semantically portable, because it has no defined semantics. To summarize, using volatile for device registers is plausible; using it for longjmp is a rank copout; using it for shared memory is premature. Has anyone else noticed that a lot of the more peculiar things that X3J11 has added (volatile, and especially noalias) are there for the benefit of compiler writers and benchmarkers, and not for the user? (I know how it happens, though; after all, I invented 'register.') Dennis Ritchie research!dmr dmr@research.att.com