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: Thu, 20 Jan 2022 16:35:06 -0800 Organization: A noiseless patient Spider Lines: 69 Message-ID: <86k0euq62t.fsf@linuxsc.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="9bbd2bd2338bc444f9d0c408d9cb7c1c"; logging-data="11819"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19K6zUktF8AAfhsahWkfKN7GOxUuWsWLp4=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:ZT8wpPWG87pbsrVIxNxNses0neM= sha1:F4DlInoRYIkWYugx43xa/wdT2/U= Xref: csiph.com comp.lang.c:164497 Andrey Tarasevich writes: > 7.1.4 Use of library functions > http://port70.net/~nsz/c/c11/n1570.html#7.1.4p1 > > 7.1.4/1 states that any function declared in a standard header can be > additionally implemented as a function-like macro (unless explicitly > stated otherwise) > > "[...] Any function declared in a header may be additionally > implemented as a function-like macro defined in the header [...]" > > It also gives some guarantees about the arguments being evaluated > exactly once > > "[...] Any invocation of a library function that is implemented as a > macro shall expand to code that evaluates each of its arguments > exactly once, fully protected by parentheses where necessary, so it is > generally safe to use arbitrary expressions as arguments. [...]" > > However, that last statement is accompanied by a footnote > > "186) Such macros might not contain the sequence points that the > corresponding function calls do" > > It appears that this footnote is intended to draw attention to the > fact that normative text does not require macro implementations to > fully match the sequencing properties of a "normal" implementation of > the same standard function. > > Is that really the case? Yes. > 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?