Re: Is it possible to generate a compile time error from an inline function?

Liste des GroupesRevenir à l c 
Sujet : Re: Is it possible to generate a compile time error from an inline function?
De : tr.17687 (at) *nospam* z991.linuxsc.com (Tim Rentsch)
Groupes : comp.lang.c
Date : 16. Jul 2024, 17:31:36
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <86plrd5p5z.fsf@linuxsc.com>
References : 1 2 3
User-Agent : Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Alan Mackenzie <acm@muc.de> writes:

Hello, Tim.
>
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
Alan Mackenzie <acm@muc.de> writes:
>
Hello, comp.lang.c.
>
What I want to do is check the validity of (constant) arguments to an
inline function, and output a compiler error if they are invalid.
>
In particular, I have:
>
    u32 __always_inline ACM_BITFIELD (u8 a[], int offset, int length)
>
, which is to extract a bitfield of LENGTH bits, starting at bit number
OFFSET in the array of bytes A.  OFFSET and LENGTH will be known at
compile time.
>
For the sake of run time efficiency, I wish to impose the restrictions
that either (i) the bitfield will be contained entirely within a byte;  or
(ii) the bitfield will be a number of consecutive whole bytes (maximum 32
bits).
>
So, for example, if the code called
>
    foo = ACM_BITFIELD (bar, 14, 4);
>
, I would like to output the compiler message "Invalid arguments 14, 4,
to ACM_BITFIELD", since this bitfield straddles two bytes.
>
Is there any way I can do this in C?  (Before anybody asks, yes I have
looked at doing it with macros, but that seems impractical, if it's even
possible.)
>
First, I don't know why you think doing this with macros is
impractical.  I knocked out a full macro version without too much
difficulty.
>
I wanted to generate code conditionally, depending on the macro's
arguments, for efficiency's sake.  I don't think this is possible - the C
preprocessor is not Lisp.  What I missed was that the compiler's
optimizer will eliminate the superfluous code anyway, so it doesn't
really matter.

Right.  Looking at code generated from my full macro implementation,
all the overhead (testing to see if the appropriate condition was
met) was optimized away, by both gcc and clang, at level O1.  So
that's pretty safe.

Second, if the C you're using has _Static_assert available, the test
can be done using that.  (Richard Damon explains how to get a
similar effect to _Static_assert for C versions before C99.)
>
_Static_assert will only work within a macro.  It doesn't work in an
inline function, whose parameters are not constant expressions, despite
being constants known at compile time.  I like the way you've got around
this, below.

Yeah.  Using _Static_assert in an expressional context needs a bit
of hoop jumping, because _Static_assert by itself is a statement,
and not an expression.  Fortunately a _Static_assert can be embedded
inside a struct definition, which can be used to accomplish the goal.

Here is an illustrating implementation in C11.  I changed the types
of the arguments offset and length to be unsigned but otherwise it
is just as you outlined.  Oh, the error message has an extra pair of
parentheses to avoid problems with macro processing.
>
Thanks.  I'll probably use something like that after my attempts last
night failed.  Just that the byte order needs to be little-endian rather
than big-endian.  Having unsigned parameters indeed makes sense, seeing
as how it eliminates trouble with negative lengths and offsets.

Here is a full macro implementation, including a little-endian byte
order.  In addition to being all-macro, I think the code here is a
little cleaner (and using little endian made the byte extraction
simpler and easier).


#define ACM_BITFIELD( bytes, offset, n )  (                             \
  ACM_IS_SUB_BYTE( offset, n )   ? ACM_BITS( bytes, offset, n )      :  \
  ACM_IS_FULL_BYTES( offset, n ) ? ACM_BYTES( bytes, offset, n )     :  \
  ACM_BITFIELD_MESSED_UP( bytes, offset, n )                            \
)

#define ACM_IS_SUB_BYTE( at, n ) (                                      \
  0 <= (at)  &&  0 < (n)  &&  (n) < 8  &&  (at)%8 + (n) <= 8            \
)

#define ACM_BITS( bytes, at, n ) (                                      \
  (bytes)[ (at)/8 ] >> (8 - (at)%8 - (n))  & ~(-1u << (n))              \
)

#define ACM_IS_FULL_BYTES( at, n ) (                                    \
  0 <= (at)  &&  (at)%8 == 0  &&  0 < (n)  &&  (n) < 33  &&  (n)%8 == 0 \
)

#define ACM_BYTES( bytes, at, n )  (                                    \
  (bytes)[(at)/8]  +  (((n) >  8 ? (bytes)[(at)/8+1] : 0u) <<  8)       \
                   +  (((n) > 16 ? (bytes)[(at)/8+2] : 0u) << 16)       \
                   +  (((n) > 24 ? (bytes)[(at)/8+3] : 0u) << 24)       \
)

#define ACM_BITFIELD_MESSED_UP( bytes, at, n ) (                        \
  (unsigned) sizeof (struct {                                           \
      int unused_irrelevant_member;                                     \
      _Static_assert(                                                   \
        ACM_IS_FULL_BYTES( at, n )  ||  ACM_IS_SUB_BYTE( at, n ),       \
        STRINGIZE( Invalid arguments (at,n) to ACM_BITFIELD )           \
      );                                                                \
   })                                                                   \
)

#define STRINGIZE(x) #x

Date Sujet#  Auteur
13 Jul 24 * Is it possible to generate a compile time error from an inline function?15Alan Mackenzie
13 Jul 24 +* Re: Is it possible to generate a compile time error from an inline function?10David Brown
13 Jul 24 i`* Re: Is it possible to generate a compile time error from an inline function?9Alan Mackenzie
13 Jul 24 i `* Re: Is it possible to generate a compile time error from an inline function?8Richard Damon
13 Jul 24 i  +* Re: Is it possible to generate a compile time error from an inline function?6Alan Mackenzie
13 Jul 24 i  i`* Re: Is it possible to generate a compile time error from an inline function?5Richard Damon
14 Jul 24 i  i +- Re: Is it possible to generate a compile time error from an inline function?1Kenny McCormack
14 Jul 24 i  i `* Re: Is it possible to generate a compile time error from an inline function?3David Brown
14 Jul 24 i  i  `* Re: Is it possible to generate a compile time error from an inline function?2Keith Thompson
14 Jul 24 i  i   `- Re: Is it possible to generate a compile time error from an inline function?1David Brown
14 Jul 24 i  `- Re: Is it possible to generate a compile time error from an inline function?1David Brown
13 Jul 24 `* Re: Is it possible to generate a compile time error from an inline function?4Tim Rentsch
14 Jul 24  `* Re: Is it possible to generate a compile time error from an inline function?3Alan Mackenzie
15 Jul 24   +- Re: Is it possible to generate a compile time error from an inline function?1Kaz Kylheku
16 Jul 24   `- Re: Is it possible to generate a compile time error from an inline function?1Tim Rentsch

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal