Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Sequencing guarantees for macro versions of standard functions Date: Mon, 24 Jan 2022 07:31:22 -0800 Organization: A noiseless patient Spider Lines: 77 Message-ID: <86zgnlm9px.fsf@linuxsc.com> References: <86k0euq62t.fsf@linuxsc.com> <87lez6xeld.fsf@nosuchdomain.example.com> <868rv5oldy.fsf@linuxsc.com> <87r18xo9o6.fsf@nosuchdomain.example.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="d742d26243a9575adb46fc0e29496190"; logging-data="3706"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18w9S4umaUx8eEkk/o9mZUMkwQlaYC+z/4=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:MwlhyYUjRSe8rfsgmHUp3t5XpoE= sha1:lVTzV8BuQP4O043UJ+Ww+w4Kn5I= Xref: csiph.com comp.lang.c:164579 Keith Thompson writes: > Tim Rentsch writes: > >> Keith Thompson writes: >> >>> Tim Rentsch writes: >>> >>>> Andrey Tarasevich writes: >>> >>> [...] >>> >>>>> Consider the following example >>>>> >>>>> double x = 1.5; >>>>> x = modf(x, &x); >>>>> >>>>> This is fine in case `modf` is actually a function. But does the >>>>> standard intend to guarantee that this is specified and defined even >>>>> if `modf` is implemented as a macro? >>>> >>>> No. >>>> >>>>> I would expect so, and it is quite possible that the following passage >>>>> >>>>> "[...] Likewise, those function-like macros described in the following >>>>> subclauses may be invoked in an expression anywhere a function with a >>>>> compatible return type could be called. [...]" >>>>> >>>>> is intended to guarantee exactly that. >>>> >>>> The quoted passage guarantees what it says: such function-like >>>> macros may be /invoked/ anywhere their corresponding functions >>>> could. It does /not/ guarantee that such invocations will work >>>> if there are sequencing issues. >>>> >>>>> But still, what exactly are they trying to point out in footnote 186? >>>> >>>> If not having the same sequencing guarantees might cause a >>>> problem (ie, if a "call" might invoke a macro rather than calling >>>> a function), avoid using a function call expression that might >>>> invoke a macro, as for example in this particular case >>>> >>>> x = (modf)( x, &x ); >>>> >>>> so that we're sure an actual function call takes place. Hence we >>>> know there will be no sequencing problems. Make sense? >>> >>> Or >>> >>> x = modf(x, &y); >>> x = y; >>> >>> (I'm already a bit uncomfortable with x = (modf)(x, &x), though >>> I know it's well defined.) >> >> I understand having a queasy reaction to 'x = (modf)(x, &x)', and >> to some degree I have such a reaction myself. I deliberately >> chose not to comment about that, since what was being asked about >> is only about sequencing issues in macros vs functions. >> >> However, the suggested rewrite has different semantics than the >> previous single assignment with function call. If we want to >> keep the same semantics but still be able to use the macro >> form (but without any sequencing issues), a different writing >> is needed, as for example >> >> x = modf( x, (double[]){ 0 } ); >> >> Writing the call this way should make it obvious that the value >> stored in/through the second argument is ignored and discarded. > > Right, I should have paid closer attention to the semantics of modf() > (which I don't think I've ever used "in anger"). Why do you make the "in anger" comment? I couldn't find any connection to earlier remarks in this thread.