_Static_assert replacement to show value in C





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















Is it possible to have the compiler error/warning diagnostic output a compile-time computed numeric value in C11 or C17 (i.e. not using templates)? The below link does this in C++ using template magic. The intention is to use this as a _Static_assert replacement which prints the values of the non-equal failed expression. Ideally, it should be able to evaluate the expression as true or false, and print only when it fails evaluation.



This is obviously compiler-dependent, so assume GCC.



Display integer at compile time in static_assert()










share|improve this question

























  • What does your "computed numeric value that is a compile-time integer value" look like?

    – Swordfish
    Nov 15 '18 at 0:53











  • e.g. sizeof(struct X)

    – Jetski S-type
    Nov 15 '18 at 0:55











  • C17 is really just C11 with some DRs fixed. No new functionality was included so it's unusual to see it referred to as a specific iteration of the standard.

    – paxdiablo
    Nov 15 '18 at 0:55











  • there is no way, even in c++. Only a compile-time string literal can be used as a second argument, no dynamic building.

    – Serge
    Nov 15 '18 at 3:32











  • @Serge You didn't click the link - click it, and see it done in C++ with templates. (Hint: not with static_assert keyword)

    – Jetski S-type
    Nov 15 '18 at 3:38


















0















Is it possible to have the compiler error/warning diagnostic output a compile-time computed numeric value in C11 or C17 (i.e. not using templates)? The below link does this in C++ using template magic. The intention is to use this as a _Static_assert replacement which prints the values of the non-equal failed expression. Ideally, it should be able to evaluate the expression as true or false, and print only when it fails evaluation.



This is obviously compiler-dependent, so assume GCC.



Display integer at compile time in static_assert()










share|improve this question

























  • What does your "computed numeric value that is a compile-time integer value" look like?

    – Swordfish
    Nov 15 '18 at 0:53











  • e.g. sizeof(struct X)

    – Jetski S-type
    Nov 15 '18 at 0:55











  • C17 is really just C11 with some DRs fixed. No new functionality was included so it's unusual to see it referred to as a specific iteration of the standard.

    – paxdiablo
    Nov 15 '18 at 0:55











  • there is no way, even in c++. Only a compile-time string literal can be used as a second argument, no dynamic building.

    – Serge
    Nov 15 '18 at 3:32











  • @Serge You didn't click the link - click it, and see it done in C++ with templates. (Hint: not with static_assert keyword)

    – Jetski S-type
    Nov 15 '18 at 3:38














0












0








0








Is it possible to have the compiler error/warning diagnostic output a compile-time computed numeric value in C11 or C17 (i.e. not using templates)? The below link does this in C++ using template magic. The intention is to use this as a _Static_assert replacement which prints the values of the non-equal failed expression. Ideally, it should be able to evaluate the expression as true or false, and print only when it fails evaluation.



This is obviously compiler-dependent, so assume GCC.



Display integer at compile time in static_assert()










share|improve this question
















Is it possible to have the compiler error/warning diagnostic output a compile-time computed numeric value in C11 or C17 (i.e. not using templates)? The below link does this in C++ using template magic. The intention is to use this as a _Static_assert replacement which prints the values of the non-equal failed expression. Ideally, it should be able to evaluate the expression as true or false, and print only when it fails evaluation.



This is obviously compiler-dependent, so assume GCC.



Display integer at compile time in static_assert()







c gcc compiler-errors c11 static-assert






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 22:57







Jetski S-type

















asked Nov 15 '18 at 0:37









Jetski S-typeJetski S-type

5001622




5001622













  • What does your "computed numeric value that is a compile-time integer value" look like?

    – Swordfish
    Nov 15 '18 at 0:53











  • e.g. sizeof(struct X)

    – Jetski S-type
    Nov 15 '18 at 0:55











  • C17 is really just C11 with some DRs fixed. No new functionality was included so it's unusual to see it referred to as a specific iteration of the standard.

    – paxdiablo
    Nov 15 '18 at 0:55











  • there is no way, even in c++. Only a compile-time string literal can be used as a second argument, no dynamic building.

    – Serge
    Nov 15 '18 at 3:32











  • @Serge You didn't click the link - click it, and see it done in C++ with templates. (Hint: not with static_assert keyword)

    – Jetski S-type
    Nov 15 '18 at 3:38



















  • What does your "computed numeric value that is a compile-time integer value" look like?

    – Swordfish
    Nov 15 '18 at 0:53











  • e.g. sizeof(struct X)

    – Jetski S-type
    Nov 15 '18 at 0:55











  • C17 is really just C11 with some DRs fixed. No new functionality was included so it's unusual to see it referred to as a specific iteration of the standard.

    – paxdiablo
    Nov 15 '18 at 0:55











  • there is no way, even in c++. Only a compile-time string literal can be used as a second argument, no dynamic building.

    – Serge
    Nov 15 '18 at 3:32











  • @Serge You didn't click the link - click it, and see it done in C++ with templates. (Hint: not with static_assert keyword)

    – Jetski S-type
    Nov 15 '18 at 3:38

















What does your "computed numeric value that is a compile-time integer value" look like?

– Swordfish
Nov 15 '18 at 0:53





What does your "computed numeric value that is a compile-time integer value" look like?

– Swordfish
Nov 15 '18 at 0:53













e.g. sizeof(struct X)

– Jetski S-type
Nov 15 '18 at 0:55





e.g. sizeof(struct X)

– Jetski S-type
Nov 15 '18 at 0:55













C17 is really just C11 with some DRs fixed. No new functionality was included so it's unusual to see it referred to as a specific iteration of the standard.

– paxdiablo
Nov 15 '18 at 0:55





C17 is really just C11 with some DRs fixed. No new functionality was included so it's unusual to see it referred to as a specific iteration of the standard.

– paxdiablo
Nov 15 '18 at 0:55













there is no way, even in c++. Only a compile-time string literal can be used as a second argument, no dynamic building.

– Serge
Nov 15 '18 at 3:32





there is no way, even in c++. Only a compile-time string literal can be used as a second argument, no dynamic building.

– Serge
Nov 15 '18 at 3:32













@Serge You didn't click the link - click it, and see it done in C++ with templates. (Hint: not with static_assert keyword)

– Jetski S-type
Nov 15 '18 at 3:38





@Serge You didn't click the link - click it, and see it done in C++ with templates. (Hint: not with static_assert keyword)

– Jetski S-type
Nov 15 '18 at 3:38












3 Answers
3






active

oldest

votes


















1














This is surprisingly difficult to get GCC to do. I found this answer: https://stackoverflow.com/a/35261673/502399 which suggests something like this:



void error() {
int array[sizeof(struct X)];
__builtin_printf("%d", &array);
}


which outputs something like




foo.c: In function ‘error’:
foo.c:8:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int (*)[8]’ [-Wformat=]

__builtin_printf("%d", &array);
~^ ~~~~~~



as long as you can pass -Wformat or -Wall or something.



To see if there's an easier way, I grepped the GCC source for that message and found that the argument type was printed with a special GCC-specific %qT format string, so I looked for other uses of that string. Specifically I was looking for its use in errors, rather than warnings, so that it would work regardless of warning flags. I found a use in binary_op_error(), from which I made this example:



int array[sizeof(struct X)];
int error = 1 / &array;


which produces




foo.c:7:15: error: invalid operands to binary / (have ‘int’ and ‘int (*)[8]’)
int error = 1 / &array;
^ ~~~~~~



other possibilities include



int array[sizeof(struct X)];
int error = __sync_fetch_and_add(&array, 1);


and



int error = _Generic((int (*)[sizeof(struct X)])0, int: 0);


and



int foo(double bar);
int error = foo((int (*)[sizeof(struct X)])0);


etc.






share|improve this answer
























  • That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

    – Jetski S-type
    Nov 15 '18 at 23:39



















1














For just displaying normal integer constants, a simple stringification macro will do:



#define STRINGIFY(x) #x
#define STR(x) STRINGIFY(x)
...
STR(123)


For the sizeof operator specifically, it gets trickier as that one is evaluated later than when macro expansion takes place in the pre-processor. Since C11 is available, you could perhaps use _Generic instead.



You can create a temporary compound literal with the size of the struct, then have _Generic compare a pointer to the created type with a pointer to another array of the expected size.



For example we can create the compound literal (char[sizeof(type)]){0} where the type char doesn't really matter, then take the address of that, &(char[sizeof(type)]){0}. Compare this type with an array pointer to an array of the expected size:



_Generic( &(char[sizeof(type)]){0}, 
char(*)[expected] : true )


Full example:



#include <stdbool.h>

#define static_size_assert(type, expected)
_Generic( &(char[sizeof(type)]){0}, char(*)[expected] : true)


int main (void)
{
typedef struct { char s[3]; int i; } foo_t;

if(static_size_assert(foo_t, 7))
{
// ...
}
return 0;
}


In case of the expected struct padding, this will cause a standard-compliant compiler to produce an error message like (from gcc):




error: '_Generic' selector of type 'char (*)[8]' is not compatible with any association




whereas static_size_assert(foo_t, 8) will compile cleanly and return true. It works as long as the number passed is a compile-time integer constant and not a variable.






share|improve this answer
























  • A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

    – Jetski S-type
    Nov 21 '18 at 0:50













  • This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

    – Jetski S-type
    Nov 21 '18 at 0:53













  • The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

    – Jetski S-type
    Nov 21 '18 at 1:24











  • #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

    – Jetski S-type
    Nov 21 '18 at 1:24













  • @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

    – Lundin
    Nov 21 '18 at 7:31



















0














Building off the answers of Lundin and Tavian, the generic solution macro for positive and negative values is as follows:



#define STATIC_ASSERT_EQUAL(VALUE, EXPECTED)                                   
(void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ?
-(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0},
char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ?
-(EXPECTED) : 0x7FFFFFFF] : 0)


The macro must be used inside a function. The idea is that EXPECTED is a value known by the programmer, and VALUE is the unknown calculated value. This was tested with GCC 6.1.



These pass without error:



STATIC_ASSERT_EQUAL(-1, -1);
STATIC_ASSERT_EQUAL(0, 0);
STATIC_ASSERT_EQUAL(1, 1);


However, this also unfortunately passes without error, because 0 aliases with 0x7FFFFFFF:



STATIC_ASSERT_EQUAL(0x7FFFFFFF, 0);


The error case appears as:



STATIC_ASSERT_EQUAL(2, 1);
error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


If you have certain warnings enabled:



STATIC_ASSERT_EQUAL(0, 1);
error: ISO C forbids zero-size array [-Werror=pedantic]


Since EXPECTED is not 0, then the programmer can assume VALUE == 0.



STATIC_ASSERT_EQUAL(-2, 1);
error: size of unnamed array is negative


The value is not displayed in this case, but the programmer can see the VALUE is negative when it shouldn't be, so negate VALUE, and it will display.



STATIC_ASSERT_EQUAL(2, -1);
error: size of unnamed array is negative


Similarly for above, the programmer knows the VALUE should be negative, but isn't, so negating VALUE will make it display.



STATIC_ASSERT_EQUAL(-2, -1);
error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


The programmer knows it should be negative, and here it displays the positive equivalent of VALUE.



STATIC_ASSERT_EQUAL(2, 0);
error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


The above zero case works as expected.






share|improve this answer


























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53310844%2fstatic-assert-replacement-to-show-value-in-c%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    This is surprisingly difficult to get GCC to do. I found this answer: https://stackoverflow.com/a/35261673/502399 which suggests something like this:



    void error() {
    int array[sizeof(struct X)];
    __builtin_printf("%d", &array);
    }


    which outputs something like




    foo.c: In function ‘error’:
    foo.c:8:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int (*)[8]’ [-Wformat=]

    __builtin_printf("%d", &array);
    ~^ ~~~~~~



    as long as you can pass -Wformat or -Wall or something.



    To see if there's an easier way, I grepped the GCC source for that message and found that the argument type was printed with a special GCC-specific %qT format string, so I looked for other uses of that string. Specifically I was looking for its use in errors, rather than warnings, so that it would work regardless of warning flags. I found a use in binary_op_error(), from which I made this example:



    int array[sizeof(struct X)];
    int error = 1 / &array;


    which produces




    foo.c:7:15: error: invalid operands to binary / (have ‘int’ and ‘int (*)[8]’)
    int error = 1 / &array;
    ^ ~~~~~~



    other possibilities include



    int array[sizeof(struct X)];
    int error = __sync_fetch_and_add(&array, 1);


    and



    int error = _Generic((int (*)[sizeof(struct X)])0, int: 0);


    and



    int foo(double bar);
    int error = foo((int (*)[sizeof(struct X)])0);


    etc.






    share|improve this answer
























    • That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

      – Jetski S-type
      Nov 15 '18 at 23:39
















    1














    This is surprisingly difficult to get GCC to do. I found this answer: https://stackoverflow.com/a/35261673/502399 which suggests something like this:



    void error() {
    int array[sizeof(struct X)];
    __builtin_printf("%d", &array);
    }


    which outputs something like




    foo.c: In function ‘error’:
    foo.c:8:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int (*)[8]’ [-Wformat=]

    __builtin_printf("%d", &array);
    ~^ ~~~~~~



    as long as you can pass -Wformat or -Wall or something.



    To see if there's an easier way, I grepped the GCC source for that message and found that the argument type was printed with a special GCC-specific %qT format string, so I looked for other uses of that string. Specifically I was looking for its use in errors, rather than warnings, so that it would work regardless of warning flags. I found a use in binary_op_error(), from which I made this example:



    int array[sizeof(struct X)];
    int error = 1 / &array;


    which produces




    foo.c:7:15: error: invalid operands to binary / (have ‘int’ and ‘int (*)[8]’)
    int error = 1 / &array;
    ^ ~~~~~~



    other possibilities include



    int array[sizeof(struct X)];
    int error = __sync_fetch_and_add(&array, 1);


    and



    int error = _Generic((int (*)[sizeof(struct X)])0, int: 0);


    and



    int foo(double bar);
    int error = foo((int (*)[sizeof(struct X)])0);


    etc.






    share|improve this answer
























    • That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

      – Jetski S-type
      Nov 15 '18 at 23:39














    1












    1








    1







    This is surprisingly difficult to get GCC to do. I found this answer: https://stackoverflow.com/a/35261673/502399 which suggests something like this:



    void error() {
    int array[sizeof(struct X)];
    __builtin_printf("%d", &array);
    }


    which outputs something like




    foo.c: In function ‘error’:
    foo.c:8:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int (*)[8]’ [-Wformat=]

    __builtin_printf("%d", &array);
    ~^ ~~~~~~



    as long as you can pass -Wformat or -Wall or something.



    To see if there's an easier way, I grepped the GCC source for that message and found that the argument type was printed with a special GCC-specific %qT format string, so I looked for other uses of that string. Specifically I was looking for its use in errors, rather than warnings, so that it would work regardless of warning flags. I found a use in binary_op_error(), from which I made this example:



    int array[sizeof(struct X)];
    int error = 1 / &array;


    which produces




    foo.c:7:15: error: invalid operands to binary / (have ‘int’ and ‘int (*)[8]’)
    int error = 1 / &array;
    ^ ~~~~~~



    other possibilities include



    int array[sizeof(struct X)];
    int error = __sync_fetch_and_add(&array, 1);


    and



    int error = _Generic((int (*)[sizeof(struct X)])0, int: 0);


    and



    int foo(double bar);
    int error = foo((int (*)[sizeof(struct X)])0);


    etc.






    share|improve this answer













    This is surprisingly difficult to get GCC to do. I found this answer: https://stackoverflow.com/a/35261673/502399 which suggests something like this:



    void error() {
    int array[sizeof(struct X)];
    __builtin_printf("%d", &array);
    }


    which outputs something like




    foo.c: In function ‘error’:
    foo.c:8:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int (*)[8]’ [-Wformat=]

    __builtin_printf("%d", &array);
    ~^ ~~~~~~



    as long as you can pass -Wformat or -Wall or something.



    To see if there's an easier way, I grepped the GCC source for that message and found that the argument type was printed with a special GCC-specific %qT format string, so I looked for other uses of that string. Specifically I was looking for its use in errors, rather than warnings, so that it would work regardless of warning flags. I found a use in binary_op_error(), from which I made this example:



    int array[sizeof(struct X)];
    int error = 1 / &array;


    which produces




    foo.c:7:15: error: invalid operands to binary / (have ‘int’ and ‘int (*)[8]’)
    int error = 1 / &array;
    ^ ~~~~~~



    other possibilities include



    int array[sizeof(struct X)];
    int error = __sync_fetch_and_add(&array, 1);


    and



    int error = _Generic((int (*)[sizeof(struct X)])0, int: 0);


    and



    int foo(double bar);
    int error = foo((int (*)[sizeof(struct X)])0);


    etc.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 15 '18 at 5:11









    Tavian BarnesTavian Barnes

    7,96233288




    7,96233288













    • That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

      – Jetski S-type
      Nov 15 '18 at 23:39



















    • That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

      – Jetski S-type
      Nov 15 '18 at 23:39

















    That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

    – Jetski S-type
    Nov 15 '18 at 23:39





    That's great! %qT in the source is a great find. Few diagnostic messages have two %qTs to display two integer values in the expression, but error: invalid operands to binary / (have ‘int(*)[10]’ and ‘int (*)[8]’) similar to yours above is one way of doing it, with two array objects. The next step is is there a way to suppress the error if the numbers are equal, but trigger the error if they are not? :)

    – Jetski S-type
    Nov 15 '18 at 23:39













    1














    For just displaying normal integer constants, a simple stringification macro will do:



    #define STRINGIFY(x) #x
    #define STR(x) STRINGIFY(x)
    ...
    STR(123)


    For the sizeof operator specifically, it gets trickier as that one is evaluated later than when macro expansion takes place in the pre-processor. Since C11 is available, you could perhaps use _Generic instead.



    You can create a temporary compound literal with the size of the struct, then have _Generic compare a pointer to the created type with a pointer to another array of the expected size.



    For example we can create the compound literal (char[sizeof(type)]){0} where the type char doesn't really matter, then take the address of that, &(char[sizeof(type)]){0}. Compare this type with an array pointer to an array of the expected size:



    _Generic( &(char[sizeof(type)]){0}, 
    char(*)[expected] : true )


    Full example:



    #include <stdbool.h>

    #define static_size_assert(type, expected)
    _Generic( &(char[sizeof(type)]){0}, char(*)[expected] : true)


    int main (void)
    {
    typedef struct { char s[3]; int i; } foo_t;

    if(static_size_assert(foo_t, 7))
    {
    // ...
    }
    return 0;
    }


    In case of the expected struct padding, this will cause a standard-compliant compiler to produce an error message like (from gcc):




    error: '_Generic' selector of type 'char (*)[8]' is not compatible with any association




    whereas static_size_assert(foo_t, 8) will compile cleanly and return true. It works as long as the number passed is a compile-time integer constant and not a variable.






    share|improve this answer
























    • A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

      – Jetski S-type
      Nov 21 '18 at 0:50













    • This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

      – Jetski S-type
      Nov 21 '18 at 0:53













    • The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

      – Jetski S-type
      Nov 21 '18 at 1:24











    • #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

      – Jetski S-type
      Nov 21 '18 at 1:24













    • @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

      – Lundin
      Nov 21 '18 at 7:31
















    1














    For just displaying normal integer constants, a simple stringification macro will do:



    #define STRINGIFY(x) #x
    #define STR(x) STRINGIFY(x)
    ...
    STR(123)


    For the sizeof operator specifically, it gets trickier as that one is evaluated later than when macro expansion takes place in the pre-processor. Since C11 is available, you could perhaps use _Generic instead.



    You can create a temporary compound literal with the size of the struct, then have _Generic compare a pointer to the created type with a pointer to another array of the expected size.



    For example we can create the compound literal (char[sizeof(type)]){0} where the type char doesn't really matter, then take the address of that, &(char[sizeof(type)]){0}. Compare this type with an array pointer to an array of the expected size:



    _Generic( &(char[sizeof(type)]){0}, 
    char(*)[expected] : true )


    Full example:



    #include <stdbool.h>

    #define static_size_assert(type, expected)
    _Generic( &(char[sizeof(type)]){0}, char(*)[expected] : true)


    int main (void)
    {
    typedef struct { char s[3]; int i; } foo_t;

    if(static_size_assert(foo_t, 7))
    {
    // ...
    }
    return 0;
    }


    In case of the expected struct padding, this will cause a standard-compliant compiler to produce an error message like (from gcc):




    error: '_Generic' selector of type 'char (*)[8]' is not compatible with any association




    whereas static_size_assert(foo_t, 8) will compile cleanly and return true. It works as long as the number passed is a compile-time integer constant and not a variable.






    share|improve this answer
























    • A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

      – Jetski S-type
      Nov 21 '18 at 0:50













    • This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

      – Jetski S-type
      Nov 21 '18 at 0:53













    • The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

      – Jetski S-type
      Nov 21 '18 at 1:24











    • #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

      – Jetski S-type
      Nov 21 '18 at 1:24













    • @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

      – Lundin
      Nov 21 '18 at 7:31














    1












    1








    1







    For just displaying normal integer constants, a simple stringification macro will do:



    #define STRINGIFY(x) #x
    #define STR(x) STRINGIFY(x)
    ...
    STR(123)


    For the sizeof operator specifically, it gets trickier as that one is evaluated later than when macro expansion takes place in the pre-processor. Since C11 is available, you could perhaps use _Generic instead.



    You can create a temporary compound literal with the size of the struct, then have _Generic compare a pointer to the created type with a pointer to another array of the expected size.



    For example we can create the compound literal (char[sizeof(type)]){0} where the type char doesn't really matter, then take the address of that, &(char[sizeof(type)]){0}. Compare this type with an array pointer to an array of the expected size:



    _Generic( &(char[sizeof(type)]){0}, 
    char(*)[expected] : true )


    Full example:



    #include <stdbool.h>

    #define static_size_assert(type, expected)
    _Generic( &(char[sizeof(type)]){0}, char(*)[expected] : true)


    int main (void)
    {
    typedef struct { char s[3]; int i; } foo_t;

    if(static_size_assert(foo_t, 7))
    {
    // ...
    }
    return 0;
    }


    In case of the expected struct padding, this will cause a standard-compliant compiler to produce an error message like (from gcc):




    error: '_Generic' selector of type 'char (*)[8]' is not compatible with any association




    whereas static_size_assert(foo_t, 8) will compile cleanly and return true. It works as long as the number passed is a compile-time integer constant and not a variable.






    share|improve this answer













    For just displaying normal integer constants, a simple stringification macro will do:



    #define STRINGIFY(x) #x
    #define STR(x) STRINGIFY(x)
    ...
    STR(123)


    For the sizeof operator specifically, it gets trickier as that one is evaluated later than when macro expansion takes place in the pre-processor. Since C11 is available, you could perhaps use _Generic instead.



    You can create a temporary compound literal with the size of the struct, then have _Generic compare a pointer to the created type with a pointer to another array of the expected size.



    For example we can create the compound literal (char[sizeof(type)]){0} where the type char doesn't really matter, then take the address of that, &(char[sizeof(type)]){0}. Compare this type with an array pointer to an array of the expected size:



    _Generic( &(char[sizeof(type)]){0}, 
    char(*)[expected] : true )


    Full example:



    #include <stdbool.h>

    #define static_size_assert(type, expected)
    _Generic( &(char[sizeof(type)]){0}, char(*)[expected] : true)


    int main (void)
    {
    typedef struct { char s[3]; int i; } foo_t;

    if(static_size_assert(foo_t, 7))
    {
    // ...
    }
    return 0;
    }


    In case of the expected struct padding, this will cause a standard-compliant compiler to produce an error message like (from gcc):




    error: '_Generic' selector of type 'char (*)[8]' is not compatible with any association




    whereas static_size_assert(foo_t, 8) will compile cleanly and return true. It works as long as the number passed is a compile-time integer constant and not a variable.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 19 '18 at 10:47









    LundinLundin

    113k17163273




    113k17163273













    • A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

      – Jetski S-type
      Nov 21 '18 at 0:50













    • This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

      – Jetski S-type
      Nov 21 '18 at 0:53













    • The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

      – Jetski S-type
      Nov 21 '18 at 1:24











    • #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

      – Jetski S-type
      Nov 21 '18 at 1:24













    • @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

      – Lundin
      Nov 21 '18 at 7:31



















    • A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

      – Jetski S-type
      Nov 21 '18 at 0:50













    • This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

      – Jetski S-type
      Nov 21 '18 at 0:53













    • The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

      – Jetski S-type
      Nov 21 '18 at 1:24











    • #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

      – Jetski S-type
      Nov 21 '18 at 1:24













    • @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

      – Lundin
      Nov 21 '18 at 7:31

















    A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

    – Jetski S-type
    Nov 21 '18 at 0:50







    A "compile-time computed numeric value" is not possible with a stringification macro, so that doesn't apply here. However, _Generic is a great way to do an equality evaluation for this.

    – Jetski S-type
    Nov 21 '18 at 0:50















    This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

    – Jetski S-type
    Nov 21 '18 at 0:53







    This is a _Static_assert replacement, so it doesn't belong in an if condition. The general macro solution that evaluates any two (positive) integers rather than just sizeof types is: #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[VALUE]){0}, char(*)[EXPECTED] : 0)

    – Jetski S-type
    Nov 21 '18 at 0:53















    The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

    – Jetski S-type
    Nov 21 '18 at 1:24





    The following is the general solution that kind of works with negative numbers, except that it aliases at 0x7FFFFFFF, so make sure that value isn't used. And negative numbers should be handled with the programmer being aware that the expected value is negative - if they have the same sign, it will print the positive of the value, and if the signs are opposite, the value will have to be negated to print the positive value.

    – Jetski S-type
    Nov 21 '18 at 1:24













    #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

    – Jetski S-type
    Nov 21 '18 at 1:24







    #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? -(EXPECTED) : 0x7FFFFFFF ] : 0)

    – Jetski S-type
    Nov 21 '18 at 1:24















    @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

    – Lundin
    Nov 21 '18 at 7:31





    @JetskiS-type It was you who wrote "it should be able to evaluate the expression as true or false and print only when it fails evaluation." Indeed that doesn't make much sense.

    – Lundin
    Nov 21 '18 at 7:31











    0














    Building off the answers of Lundin and Tavian, the generic solution macro for positive and negative values is as follows:



    #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED)                                   
    (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ?
    -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0},
    char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ?
    -(EXPECTED) : 0x7FFFFFFF] : 0)


    The macro must be used inside a function. The idea is that EXPECTED is a value known by the programmer, and VALUE is the unknown calculated value. This was tested with GCC 6.1.



    These pass without error:



    STATIC_ASSERT_EQUAL(-1, -1);
    STATIC_ASSERT_EQUAL(0, 0);
    STATIC_ASSERT_EQUAL(1, 1);


    However, this also unfortunately passes without error, because 0 aliases with 0x7FFFFFFF:



    STATIC_ASSERT_EQUAL(0x7FFFFFFF, 0);


    The error case appears as:



    STATIC_ASSERT_EQUAL(2, 1);
    error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


    If you have certain warnings enabled:



    STATIC_ASSERT_EQUAL(0, 1);
    error: ISO C forbids zero-size array [-Werror=pedantic]


    Since EXPECTED is not 0, then the programmer can assume VALUE == 0.



    STATIC_ASSERT_EQUAL(-2, 1);
    error: size of unnamed array is negative


    The value is not displayed in this case, but the programmer can see the VALUE is negative when it shouldn't be, so negate VALUE, and it will display.



    STATIC_ASSERT_EQUAL(2, -1);
    error: size of unnamed array is negative


    Similarly for above, the programmer knows the VALUE should be negative, but isn't, so negating VALUE will make it display.



    STATIC_ASSERT_EQUAL(-2, -1);
    error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


    The programmer knows it should be negative, and here it displays the positive equivalent of VALUE.



    STATIC_ASSERT_EQUAL(2, 0);
    error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


    The above zero case works as expected.






    share|improve this answer






























      0














      Building off the answers of Lundin and Tavian, the generic solution macro for positive and negative values is as follows:



      #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED)                                   
      (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ?
      -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0},
      char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ?
      -(EXPECTED) : 0x7FFFFFFF] : 0)


      The macro must be used inside a function. The idea is that EXPECTED is a value known by the programmer, and VALUE is the unknown calculated value. This was tested with GCC 6.1.



      These pass without error:



      STATIC_ASSERT_EQUAL(-1, -1);
      STATIC_ASSERT_EQUAL(0, 0);
      STATIC_ASSERT_EQUAL(1, 1);


      However, this also unfortunately passes without error, because 0 aliases with 0x7FFFFFFF:



      STATIC_ASSERT_EQUAL(0x7FFFFFFF, 0);


      The error case appears as:



      STATIC_ASSERT_EQUAL(2, 1);
      error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


      If you have certain warnings enabled:



      STATIC_ASSERT_EQUAL(0, 1);
      error: ISO C forbids zero-size array [-Werror=pedantic]


      Since EXPECTED is not 0, then the programmer can assume VALUE == 0.



      STATIC_ASSERT_EQUAL(-2, 1);
      error: size of unnamed array is negative


      The value is not displayed in this case, but the programmer can see the VALUE is negative when it shouldn't be, so negate VALUE, and it will display.



      STATIC_ASSERT_EQUAL(2, -1);
      error: size of unnamed array is negative


      Similarly for above, the programmer knows the VALUE should be negative, but isn't, so negating VALUE will make it display.



      STATIC_ASSERT_EQUAL(-2, -1);
      error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


      The programmer knows it should be negative, and here it displays the positive equivalent of VALUE.



      STATIC_ASSERT_EQUAL(2, 0);
      error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


      The above zero case works as expected.






      share|improve this answer




























        0












        0








        0







        Building off the answers of Lundin and Tavian, the generic solution macro for positive and negative values is as follows:



        #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED)                                   
        (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ?
        -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0},
        char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ?
        -(EXPECTED) : 0x7FFFFFFF] : 0)


        The macro must be used inside a function. The idea is that EXPECTED is a value known by the programmer, and VALUE is the unknown calculated value. This was tested with GCC 6.1.



        These pass without error:



        STATIC_ASSERT_EQUAL(-1, -1);
        STATIC_ASSERT_EQUAL(0, 0);
        STATIC_ASSERT_EQUAL(1, 1);


        However, this also unfortunately passes without error, because 0 aliases with 0x7FFFFFFF:



        STATIC_ASSERT_EQUAL(0x7FFFFFFF, 0);


        The error case appears as:



        STATIC_ASSERT_EQUAL(2, 1);
        error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


        If you have certain warnings enabled:



        STATIC_ASSERT_EQUAL(0, 1);
        error: ISO C forbids zero-size array [-Werror=pedantic]


        Since EXPECTED is not 0, then the programmer can assume VALUE == 0.



        STATIC_ASSERT_EQUAL(-2, 1);
        error: size of unnamed array is negative


        The value is not displayed in this case, but the programmer can see the VALUE is negative when it shouldn't be, so negate VALUE, and it will display.



        STATIC_ASSERT_EQUAL(2, -1);
        error: size of unnamed array is negative


        Similarly for above, the programmer knows the VALUE should be negative, but isn't, so negating VALUE will make it display.



        STATIC_ASSERT_EQUAL(-2, -1);
        error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


        The programmer knows it should be negative, and here it displays the positive equivalent of VALUE.



        STATIC_ASSERT_EQUAL(2, 0);
        error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


        The above zero case works as expected.






        share|improve this answer















        Building off the answers of Lundin and Tavian, the generic solution macro for positive and negative values is as follows:



        #define STATIC_ASSERT_EQUAL(VALUE, EXPECTED)                                   
        (void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ?
        -(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0},
        char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ?
        -(EXPECTED) : 0x7FFFFFFF] : 0)


        The macro must be used inside a function. The idea is that EXPECTED is a value known by the programmer, and VALUE is the unknown calculated value. This was tested with GCC 6.1.



        These pass without error:



        STATIC_ASSERT_EQUAL(-1, -1);
        STATIC_ASSERT_EQUAL(0, 0);
        STATIC_ASSERT_EQUAL(1, 1);


        However, this also unfortunately passes without error, because 0 aliases with 0x7FFFFFFF:



        STATIC_ASSERT_EQUAL(0x7FFFFFFF, 0);


        The error case appears as:



        STATIC_ASSERT_EQUAL(2, 1);
        error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


        If you have certain warnings enabled:



        STATIC_ASSERT_EQUAL(0, 1);
        error: ISO C forbids zero-size array [-Werror=pedantic]


        Since EXPECTED is not 0, then the programmer can assume VALUE == 0.



        STATIC_ASSERT_EQUAL(-2, 1);
        error: size of unnamed array is negative


        The value is not displayed in this case, but the programmer can see the VALUE is negative when it shouldn't be, so negate VALUE, and it will display.



        STATIC_ASSERT_EQUAL(2, -1);
        error: size of unnamed array is negative


        Similarly for above, the programmer knows the VALUE should be negative, but isn't, so negating VALUE will make it display.



        STATIC_ASSERT_EQUAL(-2, -1);
        error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


        The programmer knows it should be negative, and here it displays the positive equivalent of VALUE.



        STATIC_ASSERT_EQUAL(2, 0);
        error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association


        The above zero case works as expected.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 21 '18 at 1:45

























        answered Nov 21 '18 at 1:40









        Jetski S-typeJetski S-type

        5001622




        5001622






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53310844%2fstatic-assert-replacement-to-show-value-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?