Static assert in C

前端 未结 12 714
感情败类
感情败类 2020-11-22 16:22

What\'s the best way to achieve compile time static asserts in C (not C++), with particular emphasis on GCC?

12条回答
  •  执念已碎
    2020-11-22 16:49

    For those of you wanting something really basic and portable but don't have access to C++11 features, I've written just the thing.
    Use STATIC_ASSERT normally (you can write it twice in the same function if you want) and use GLOBAL_STATIC_ASSERT outside of functions with a unique phrase as the first parameter.

    #if defined(static_assert)
    #   define STATIC_ASSERT static_assert
    #   define GLOBAL_STATIC_ASSERT(a, b, c) static_assert(b, c)
    #else
    #   define STATIC_ASSERT(pred, explanation); {char assert[1/(pred)];(void)assert;}
    #   define GLOBAL_STATIC_ASSERT(unique, pred, explanation); namespace ASSERTATION {char unique[1/(pred)];}
    #endif
    
    GLOBAL_STATIC_ASSERT(first, 1, "Hi");
    GLOBAL_STATIC_ASSERT(second, 1, "Hi");
    
    int main(int c, char** v) {
        (void)c; (void)v;
        STATIC_ASSERT(1 > 0, "yo");
        STATIC_ASSERT(1 > 0, "yo");
    //    STATIC_ASSERT(1 > 2, "yo"); //would compile until you uncomment this one
        return 0;
    }
    

    Explanation:
    First it checks if you have the real assert, which you would definitely want to be using if it's available.
    If you don't it asserts by getting your predicate, and dividing it by itself. This does two things.
    If it's zero, id est, the assertion has failed, it will cause a divide by zero error (the arithmetic is forced because it is trying to declare an array).
    If it is not zero, it normalises the array size to 1. So if the assertion passed, you wouldn't want it to fail anyway because your predicate evaluated to -1 (invalid), or be 232442 (massive waste of space, IDK if it would be optimised out).
    For STATIC_ASSERT it is wrapped in braces, this makes it a block, which scopes the variable assert, meaning you can write it many times.
    It also casts it to void, which is a known way to get rid of unused variable warnings.
    For GLOBAL_STATIC_ASSERT, instead of being in a code block, it generates a namespace. Namespaces are allowed outside of functions. A unique identifier is required to stop any conflicting definitions if you use this one more than once.


    Worked for me on GCC and VS'12 C++

提交回复
热议问题