🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.c.moderated
Article #2482

Re: Interesting compile-time assertion macro

#2482
From: Thad Smith
Date: Wed, 03 Apr 1996 13:12
60 lines
2935 bytes
In article <4jq1lg$a67@solutions.solon.com>,
Mike Coffman <coffman@cat.com> wrote:
>Mike Haertel wrote in comp.lang.c.moderated:
>> So I came up with a compile-time equivalent of <assert.h>:
>> 
>> /*
>>  * Cause a compile-time error if the asserted expression, which
>>  * must be a constant expression according to the rules of ANSI C,
>>  * is false.  Each use of this macro must supply a different
>>  * identifier for KEY.
>>  *
>>  * It works by trying to declare an array of negative size if
>>  * the asserted expression is false.
>>  */
>> #define ASSERT_COMPILE_TIME(EXPR, KEY)                                  \
>>         struct ASSERT_COMPILE_TIME_##KEY {                              \
>>                 char ASSERT_COMPILE_TIME_##KEY[2*((EXPR) != 0) - 1];    \
>>         }
>
>Mike:
>I like the principle of protecting the users of source code that I write 
>from the mistakes they make adjusting the parameters to their
>application.
>I usually use the sequence:
> 
>#if test_condition
>#error error message
>#endif 
>
>but, as you can see, this takes three lines to invoke to your one.

The other problem is that the preprocessor doesn't have access to the
full power of constant expressions invoving sizeof, offsetof, etc.

I found Mike Haertel's macro clever and inspiring.  I suggested in
email that the struct name could be omitted, so that the KEY
parameter isn't required.  He responded that the gcc produced a
warning for such a declaration.  I have put together a version which
concatenates __LINE__ to a symbol to make it unique:

 /* ASSERT_COMPILE_TIME() allows a constant expression to be evaluated
 ** at compile time.  It causes an error, due to negative array size,
 ** if the expression is false.  It must be placed where declarations
 ** are allowed.
 ** Adapted from posting 1 Apr 1996 in comp.lang.c.moderated by
 ** haertel@ichips.intel.com (Mike Haertel).
 */
 #define ASSERT_CAT1(x) ASSERT_CAT ## x
 #define ASSERT_CAT0(x) ASSERT_CAT1(x)
 #define ASSERT_COMPILE_TIME(expr)  \
         struct ASSERT_CAT0(__LINE__){char t[2*!!(expr)-1];}

>The only overhead/disadvantage to your technique is that once I get my
>code to compile successfully I have a number of structures composed of
>one element character arrays taking up a little space.

Not really.  A struct is defined, but not declared, i.e., there is no
struct variable so no space is taken.  :-)

Thad
Technical Details
Message-ID: <4jttgb$3n3@solutions.solon.com>
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
References: <4jol55$1pi@solutions.solon.com> <4jq1lg$a67@solutions.solon.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
From: thads@csn.net (Thad Smith)
Newsgroups: comp.lang.c.moderated
Subject: Re: Interesting compile-time assertion macro
Date: 3 Apr 1996 07:12:43 -0600
Organization: T3 Systems
Sender: clc@solutions.solon.com
Approved: clc@solutions.solon.com
Message-ID: <4jttgb$3n3@solutions.solon.com>
References: <4jol55$1pi@solutions.solon.com> <4jq1lg$a67@solutions.solon.com>
Reply-To: ThadSmith@acm.org
NNTP-Posting-Host: solutions.solon.com