[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] What is the necessity of _FFS() ?
From: |
Dmitry K. |
Subject: |
Re: [avr-libc-dev] What is the necessity of _FFS() ? |
Date: |
Thu, 20 Oct 2005 19:11:10 +1100 |
User-agent: |
KMail/1.5 |
On Thursday 20 October 2005 16:01, Joerg Wunsch wrote:
> As Dmitry K. wrote:
> > What is the reason of '_FFS' appearance in the last Avr-libc CVS?
>
> ffs() is a function, and should remain a function. It violates the
> principle of least astonishment (POLA) to suddenly have a macro by
> that name that does magic things on its arguments -- among them,
> evaluating its argument at least twice. Think about people who'd
> innocently do something like
>
> ...
> i = ffs(getsomevalue());
> ...
>
> or even worse:
>
> i = ffs(rand());
>
> (where rand() clearly returns a different value for each call).
Original implementation of 'ffs' is absolutely safe.
'__buitin_constant_p' is *not* evaluate argument.
Like 'sizeof': the function
int foo (x)
{
sizeof (x++);
return x;
}
returns unchanged 'x'. (I have check this with and without
optimization.)
I have check 2 functions with original ffs macro:
int foo1 (int x)
{
return ffs(++x);
}
int foo2 (int x)
{
return ffs(rand(x));
}
With optimization result is:
foo1:
adiw r24,1
rcall ffs
ret
foo2:
rcall rand
rcall ffs
ret
Without optimization:
foo1:
...
/* prologue end (size=10) */
std Y+1,r24
std Y+2,r25
ldd r24,Y+1
ldd r25,Y+2
adiw r24,1
std Y+1,r24
std Y+2,r25
rcall ffs
/* epilogue: frame size=2 */
...
foo2:
/* prologue end (size=10) */
std Y+1,r24
std Y+2,r25
ldd r24,Y+1
ldd r25,Y+2
rcall rand
rcall ffs
/* epilogue: frame size=2 */
Both funcions produce correct code with and without optimization.
[...]
> I've then asked Anatoly what's the purpose of the macro implementation
> at all, and he passed me your opinion on about having something like a
> counterpart to _BV().
I wished to emphasize only, that the 'ffs' with constant
argument is not exotic.
[...]
> (*) Historical exceptions are getc and putc, but for them, it has
> always been clearly stated they might be implemented as macros that
> evaluate their argument more than once (even though they aren't in our
> case, as our stdio does no buffering).
There are many functions, that are implemented as macroses:
sin, cos, tan, sqrt ... (This is a C99 standart, to evaluate a size
of argument: float, double or long double).
Glibc with __GNUC__ defined: big part of standart string functions
are macroses for efficiency (__builtin_constant_p is used activly).
Thanks,
Dmitry.