[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

quest for cross-platform static assert

Francois Grieu

4/19/2011 3:13:00 PM

Under C89/90/99, there is no static assert allowing to check a
constant expression at compile time. I often use

#define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]

e.g. in

ASSERT_S(sizeof(foo)>=sizeof(bar));
memcpy(foo,bar,sizeof(bar));


But on some platforms there is a spurious warning or link time error
(which I can't remember, and that would be OT). On these platforms
I end up using

#define ASSERT_S(condition) struct{char assert_s[(condition)?1:-1];}

but it causes other issues on some other platforms. I recall things
depend on if ASSERT_S is used in global or function scope.

There is

#define ASSERT_S(condition) enum{ASSERT_Sy(__LINE__)=sizeof(char[(condition)?1:-1])}
#define ASSERT_Sy(j) ASSERT_Sz(j)
#define ASSERT_Sz(j) assert_s##j

and it often works fine, but using that ASSERT_S twice on same-numbered
lines (e.g twice on a line, or different but same-numbered lines in different
header files used in the same compilation unit) will fail.


Except when __COUNTER__ is available, workarounds get hairy:
#define ASSERT_S(condition) enum{ASSERT_Sy(__LINE__,HDR_NAME)=sizeof(char[(condition)?1:-1])}
#define ASSERT_Sy(j,n) ASSERT_Sz(j,n)
#define ASSERT_Sz(j,n) assert_s##j##n

with the convention that any header file should be structured as
#include "other_header.h"
#define HDR_NAME myuniquename
/* here ASSERT_S is usable */
#undef HDR_NAME


Can this be improved upon, towards the grail of working almost everywhere
without special-casing for this or that environment?

TIA,
Francois Grieu
20 Answers

Chris H

4/19/2011 5:04:00 PM

0

In message <4dada675$0$7171$426a74cc@news.free.fr>, Francois Grieu
<fgrieu@gmail.com> writes
>Under C89/90/99, there is no static assert allowing to check a
>constant expression at compile time.

Snip

>Can this be improved upon, towards the grail of working almost everywhere
>without special-casing for this or that environment?

It is not a holy grail. Most don't care about portability. Most of those
who do only care for a very small sub set of environments.

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/



christian.bau

4/19/2011 5:14:00 PM

0

On Apr 19, 4:13 pm, Francois Grieu <fgr...@gmail.com> wrote:
> Under C89/90/99, there is no static assert allowing to check a
> constant expression at compile time. I often use
>
> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]

switch statement with two cases, one case 0: and one case
yourcondition: If the condition is false, you have two case labels =
0, and I haven't seen a compiler accepting it, and I haven't seen a
compiler giving warnings about it. For example

switch (0) { case 0: case sizeof (long) == 4: ; }

(in some macro obviously).

Francois Grieu

4/19/2011 5:32:00 PM

0

On 19/04/2011 19:13, christian.bau wrote:
> On Apr 19, 4:13 pm, Francois Grieu<fgr...@gmail.com> wrote:
>> Under C89/90/99, there is no static assert allowing to check a
>> constant expression at compile time. I often use
>>
>> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]
>
> switch statement with two cases, one case 0: and one case
> yourcondition: If the condition is false, you have two case labels =
> 0, and I haven't seen a compiler accepting it, and I haven't seen a
> compiler giving warnings about it. For example
>
> switch (0) { case 0: case sizeof (long) == 4: ; }
>
> (in some macro obviously).

Obvious drawbacks:
- not usable in a header file.
- generates code on many platforms.

Francois Grieu

Francois Grieu

4/19/2011 5:35:00 PM

0

On 19/04/2011 19:03, Chris H wrote:
> In message<4dada675$0$7171$426a74cc@news.free.fr>, Francois Grieu
> <fgrieu@gmail.com> writes
>> Under C89/90/99, there is no static assert allowing to check a
>> constant expression at compile time.
>
> Snip
>
>> Can this be improved upon, towards the grail of working almost everywhere
>> without special-casing for this or that environment?
>
> It is not a holy grail. Most don't care about portability. Most of those
> who do only care for a very small sub set of environments.

Most pursue other grails than me.

Francois Grieu

ImpalerCore

4/20/2011 1:43:00 PM

0

On Apr 19, 11:13 am, Francois Grieu <fgr...@gmail.com> wrote:
> Under C89/90/99, there is no static assert allowing to check a
> constant expression at compile time. I often use
>
> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]
>
> e.g. in
>
> ASSERT_S(sizeof(foo)>=sizeof(bar));
> memcpy(foo,bar,sizeof(bar));
>
> But on some platforms there is a spurious warning or link time error
> (which I can't remember, and that would be OT). On these platforms
> I end up using
>
> #define ASSERT_S(condition) struct{char assert_s[(condition)?1:-1];}
>
> but it causes other issues on some other platforms. I recall things
> depend on if ASSERT_S is used in global or function scope.
>
> There is
>
> #define ASSERT_S(condition) enum{ASSERT_Sy(__LINE__)=sizeof(char[(condition)?1:-1])}
> #define ASSERT_Sy(j) ASSERT_Sz(j)
> #define ASSERT_Sz(j) assert_s##j
>
> and it often works fine, but using that ASSERT_S twice on same-numbered
> lines (e.g twice on a line, or different but same-numbered lines in different
> header files used in the same compilation unit) will fail.
>
> Except when __COUNTER__ is available, workarounds get hairy:
> #define ASSERT_S(condition) enum{ASSERT_Sy(__LINE__,HDR_NAME)=sizeof(char[(condition)?1:-1])}
> #define ASSERT_Sy(j,n) ASSERT_Sz(j,n)
> #define ASSERT_Sz(j,n) assert_s##j##n
>
> with the convention that any header file should be structured as
> #include "other_header.h"
> #define HDR_NAME myuniquename
> /* here ASSERT_S is usable */
> #undef HDR_NAME
>
> Can this be improved upon, towards the grail of working almost everywhere
> without special-casing for this or that environment?

Not sure if you would consider this an improvement, but my version
parameterizes the name.

\code snippet
#define C_STATIC_ASSERT(name, expr) extern char (name)[(expr) ? 1 :
-1]

C_STATIC_ASSERT( CHAR_BIT_is_8_bits, CHAR_BIT == 8 );
C_STATIC_ASSERT( sizeof_int_at_least_32_bits, sizeof(int) >= 4 );
\endcode

That way, when you get a failure, you get the label in the error
output like this:

C_STATIC_ASSERT_example.c:4: error: size of array
`sizeof_int_at_least_32_bits' is negative.

You could try giving each static assertion a unique name and see if
it's more portable in your environments.

Best regards,
John D.

Tim Rentsch

4/20/2011 6:05:00 PM

0

Francois Grieu <fgrieu@gmail.com> writes:

> Under C89/90/99, there is no static assert allowing to check a
> constant expression at compile time. I often use
>
> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]
>
> e.g. in
>
> ASSERT_S(sizeof(foo)>=sizeof(bar));
> memcpy(foo,bar,sizeof(bar));
>
>
> But on some platforms there is a spurious warning or link time error
> (which I can't remember, and that would be OT). [snip alternatives]

Any reason you can't simply add a definition (perhaps in its
own separate .c file) for the symbol in question? I know it
adds some configuration overhead that you may not want to
add, but it would seem to completely solve the portability
problem.

Francois Grieu

4/21/2011 8:34:00 AM

0

On 20/04/2011 20:04, Tim Rentsch wrote:
> Francois Grieu<fgrieu@gmail.com> writes:
>
>> Under C89/90/99, there is no static assert allowing to check a
>> constant expression at compile time. I often use
>>
>> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]
>>
>> e.g. in
>>
>> ASSERT_S(sizeof(foo)>=sizeof(bar));
>> memcpy(foo,bar,sizeof(bar));
>>
>>
>> But on some platforms there is a spurious warning or link time error
>> (which I can't remember, and that would be OT). [snip alternatives]
>
> Any reason you can't simply add a definition (perhaps in its
> own separate .c file) for the symbol in question? I know it
> adds some configuration overhead that you may not want to
> add, but it would seem to completely solve the portability
> problem.

I remember using this workaround, with success, on I-can't-remember-what
platform where the linker complained. Having to bundle a .c file just for
that is a pain (currently my "commonstuff" header has no such requirement).

And I tried again that variant of ASSERT_S on a platform where I
currently special-case to use the dummy-struct technique, and got that
spurious compiler warning:
#warning cpstm7 sha1.c:75(2+15) assert_failure unused

This happens when ASSERT_S is used in function scope. Quite logical.

BTW, I also have the variant below which has been 100% portable so far,
but has the drawback of being usable only in function scope and after
the last variable declaration (by contract, ASSERT_S is usable anywhere
a declaration is possible).

#define ASSERT_F(condition) do;while(!sizeof(char[(condition)?1:-1]))


Francois Grieu

Chris H

4/21/2011 9:01:00 AM

0

In message <4dadc7c3$0$26043$426a74cc@news.free.fr>, Francois Grieu
<fgrieu@gmail.com> writes
>On 19/04/2011 19:03, Chris H wrote:
>> In message<4dada675$0$7171$426a74cc@news.free.fr>, Francois Grieu
>> <fgrieu@gmail.com> writes
>>> Under C89/90/99, there is no static assert allowing to check a
>>> constant expression at compile time.
>>
>> Snip
>>
>>> Can this be improved upon, towards the grail of working almost everywhere
>>> without special-casing for this or that environment?
>>
>> It is not a holy grail. Most don't care about portability. Most of those
>> who do only care for a very small sub set of environments.
>
>Most pursue other grails than me.
>
> Francois Grieu

SO why do you want to be able to run on a PIC, PowerPC, Alpha, MIPS,
ARM, 8051 and x86?


--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/



Eric Sosman

4/21/2011 12:14:00 PM

0

On 4/21/2011 4:34 AM, Francois Grieu wrote:
> On 20/04/2011 20:04, Tim Rentsch wrote:
>> Francois Grieu<fgrieu@gmail.com> writes:
>>
>>> Under C89/90/99, there is no static assert allowing to check a
>>> constant expression at compile time. I often use
>>>
>>> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]
>>> [...]
>>> But on some platforms there is a spurious warning or link time error
>>> (which I can't remember, and that would be OT). [snip alternatives]
>>
>> Any reason you can't simply add a definition (perhaps in its
>> own separate .c file) for the symbol in question? [...]
>
> I remember using this workaround,[...]

Peculiar use of "workaround," don't you think? You promise the
compiler that some other compilation unit defines `assert_failure',
and it's a "workaround" to provide the promised definition? And the
complaint when you renege on your promise is "spurious?"

Ever hear the one about the guy who murdered his parents and
asked the court for mercy because he was an orphan?

--
Eric Sosman
esosman@ieee-dot-org.invalid

Francois Grieu

4/21/2011 5:10:00 PM

0

On 21/04/2011 14:13, Eric Sosman wrote:
> On 4/21/2011 4:34 AM, Francois Grieu wrote:
>> On 20/04/2011 20:04, Tim Rentsch wrote:
>>> Francois Grieu<fgrieu@gmail.com> writes:
>>>
>>>> Under C89/90/99, there is no static assert allowing to check a
>>>> constant expression at compile time. I often use
>>>>
>>>> #define ASSERT_S(condition) extern char assert_failure[(condition)?1:-1]
>>>> [...]
>>>> But on some platforms there is a spurious warning or link time error
>>>> (which I can't remember, and that would be OT). [snip alternatives]
>>>
>>> Any reason you can't simply add a definition (perhaps in its
>>> own separate .c file) for the symbol in question? [...]
>>
>> I remember using this workaround,[...]
>
> Peculiar use of "workaround," don't you think? You promise the
> compiler that some other compilation unit defines `assert_failure',
> and it's a "workaround" to provide the promised definition? And the
> complaint when you renege on your promise is "spurious?"

On the other hand, I never make a reference to that assert_failure[],
therefore it seems at least allowable that the linker does not complain
or/and that the compiler does not even inform the linker about that
assert_failure[] thing. That happens on most of my platforms.

> Ever hear the one about the guy who murdered his parents and
> asked the court for mercy because he was an orphan?

That guy was adopted.


Francois Grieu