Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!elroy.jpl.nasa.gov!jarthur!uunet!viusys!uxui!unislc!dave From: dave@unislc.uucp (Dave Martin) Newsgroups: comp.sys.amiga.programmer Subject: Re: ANOTHER SAS C BUG Message-ID: <1991Apr5.004856.21757@unislc.uucp> Date: 5 Apr 91 00:48:56 GMT References: <1991Mar31.035009.13183@csis.dit.csiro.au> Organization: unisys Lines: 92 From article <1991Mar31.035009.13183@csis.dit.csiro.au>, by dave@csis.dit.csiro.au (David Campbell): > /* Here is some source which demonstrates a bug in the SAS C > compiler */ > > #include > > char *str="hello\n"; > > main() > { > char *ptr; > > ptr = str; > *ptr = '\001' + *ptr++; > printf(str); > } > > > /* Should print "iello" through the incrementing of str[0] > > Instead prints "hillo" why "should" it? I don't know what K&R say (probably nothing about this) but ANSI C Draft Dec 7 1988 (I wish I had a more recent version) says 3.3 Expressions ... Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. (see footnote 31) footnote 31 says: This paragraph renders undefined statement expressions such as i = ++i + 1; while allowing i = i + 1; > *ptr = '\001' + *ptr++; You have asked the compiler to fetch *ptr which is 'h', increment ptr (it now points to 'e') add '\001' (or 1) to 'h' and store the value through ptr (which has since been incremented). This statement isn't guaranteed to work "right" either: *(ptr++) = '\001' + *ptr; You can change this to *ptr = '\001' + *ptr; ptr++; The safest thing to do is increment the pointer in a separate statement. Also, in the Rationale document section 2.1.2.3 program execution: Because C expressions can contain side effects, issues of sequencing are important in expression evaluation. (see 3.3) Most operators IMPOSE NO SEQUENCING REQUIREMENTS, [emphasis added by me] but a few operators impose sequence points upon the evaluation: comma, logical-AND, logical-OR and conditional. For example, in the expression (i = 1, a[i] = 0) the side effect (alteration to storage) specified by i = 1 must be completed before the expression a[i] = 0 is evaluated. Note that = (assignment) is NOT one of the listed operators. the compiler can perform the ++ in *str++ before OR after the assignment. You are assuming that it will be completed after the assignment, while the compiler chooses to complete it after the value 'h' is retrieved. The compiler (and SAS/C claims to be ANSI compliant) can legally do this under ANSI-C. K&R probably said nothing about this and the compiler can do what it wants. (sidenote: SAS/C still needs to implement long double and I hope they do it (at least under the -f8 (use FPU) option) as FPU type X (extended). This is the most efficient mode for the FPU anyway as it does all its math in X format.) If someone can confirm (or "fix") my interpretation of the ANSI standard here, I would appreciate it. (this is why we have lawyers... 8-)). -- VAX Headroom Speaking for myself only... blah blah blahblah blah... Internet: DMARTIN@CC.WEBER.EDU dave@saltlcy-unisys.army.mil uucp: dave@unislc.uucp or use the Path: line. Now was that civilized? No, clearly not. Fun, but in no sense civilized.