Способы ASSERT выражений во время сборки в C

Нечетные категории и четные категории обращаются назад.

Индексы начинают a 0 не 1

0% 2 = 0

0 индекс нечетный.

var oddCategories  = projectsByCat.Where((cat, index) => index % 2 == 0);

var evenCategories = projectsByCat.Where((cat, index) => index % 2 != 0);
25
задан 10 revs, 4 users 78% 21 June 2013 в 15:20
поделиться

8 ответов

НОВЫЙ ОТВЕТ :

В моем исходном ответе (ниже), у меня должно было быть два различных макросов для поддержки утверждений в функциональном объеме и в глобальной области видимости. Я задался вопросом, было ли возможно предложить единое решение, которое работало бы в обоих объемах.

я смог найти решение, которое работало на компиляторы Visual Studio и Comeau с помощью символьных массивов экстерна. Но я смог найти более сложное решение, которое работает на GCC. Но решение GCC не работает на Visual Studio.: (Но добавление '#ifdef __ GNUC __ ', легко выбрать правильный набор макросов для данного компилятора.

Решение:

#ifdef __GNUC__
#define STATIC_ASSERT_HELPER(expr, msg) \
    (!!sizeof \ (struct { unsigned int STATIC_ASSERTION__##msg: (expr) ? 1 : -1; }))
#define STATIC_ASSERT(expr, msg) \
    extern int (*assert_function__(void)) [STATIC_ASSERT_HELPER(expr, msg)]
#else
    #define STATIC_ASSERT(expr, msg)   \
    extern char STATIC_ASSERTION__##msg[1]; \
    extern char STATIC_ASSERTION__##msg[(expr)?1:2]
#endif /* #ifdef __GNUC__ */

Вот сообщения об ошибках, о которых сообщают для STATIC_ASSERT(1==1, test_message); в строке 22 из test.c:

GCC:

line 22: error: negative width in bit-field `STATIC_ASSERTION__test_message'

Visual Studio:

test.c(22) : error C2369: 'STATIC_ASSERTION__test_message' : redefinition; different subscripts
    test.c(22) : see declaration of 'STATIC_ASSERTION__test_message'

Comeau:

line 22: error: declaration is incompatible with
        "char STATIC_ASSERTION__test_message[1]" (declared at line 22)

 
 

ИСХОДНЫЙ ОТВЕТ :

я делаю что-то очень похожее на то, какие Средства проверки делает. Но я включаю сообщение, которое это разоблачит во многих компиляторах:

#define STATIC_ASSERT(expr, msg)               \
{                                              \
    char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
    (void)STATIC_ASSERTION__##msg[0];          \
}

И для того, чтобы сделать что-то в глобальной области видимости (вне функции) использует это:

#define GLOBAL_STATIC_ASSERT(expr, msg)   \
  extern char STATIC_ASSERTION__##msg[1]; \
  extern char STATIC_ASSERTION__##msg[(expr)?1:2]
27
ответ дан Ken Bloom 21 June 2013 в 15:20
поделиться
  • 1
    Спасибо, но почему там точка с запятой перед С пунктом? – Rafid 4 November 2011 в 09:51

Существует статья Ralf Holly , который исследует различные варианты на помехи, утверждает в C.

Он представляет три разных подхода:

  • значения случая переключателя должны быть уникальны
  • , массивы не должны иметь отрицательных размеров
  • деление на нуль для константных выражений

, Его заключение для лучшей реализации - это:

#define assert_static(e) \
    do { \
        enum { assert_static__ = 1/(e) }; \
    } while (0)
14
ответ дан 2 revs, 2 users 97% 21 June 2013 в 15:20
поделиться
  • 1
    @Promather - it' s там, потому что WITH ключевое слово может иметь другие значения, и представлять CTE, это должен быть запуск оператора. Точка с запятой гарантирует, что предыдущий оператор определенно завершается. – Damien_The_Unbeliever 4 November 2011 в 10:00

Любой из методов, перечисленных здесь, должен работать и когда C++ 0x станет доступным, Вы будете в состоянии использовать встроенное static_assert ключевое слово.

5
ответ дан jwfearn 21 June 2013 в 15:20
поделиться
  • 1
    Хорошо прохладный Вы знаете, как создать компонент? Просто необходимо создать компонент и затем добавить маршрут как это, {путь: ' login' компонент: LoginComponent} – wuno 16 February 2017 в 19:39

Попытка:

#define STATIC_ASSERT(x, error) \
do { \
    static const char error[(x)?1:-1];\
} while(0)

Тогда можно записать:

STATIC_ASSERT(a == b, a_not_equal_to_b);

, Который может дать Вам лучшее сообщение об ошибке (в зависимости от Вашего компилятора).

5
ответ дан Evan Teran 21 June 2013 в 15:20
поделиться

Общая, портативная опция

#if 5 != (state1|mode1)
#    error "aaugh!"
#endif

, но она не работает в этом случае, потому что они - константы C и не #define с.

Вы видите ядро Linux BUILD_BUG_ON макрос для чего-то, что обрабатывает Ваш случай:

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

, Когда condition верно, это становится ((void)sizeof(char[-1])), который недопустим и должен перестать работать во время компиляции, и иначе это становится ((void)sizeof(char[1])), который является очень хорошо.

3
ответ дан ephemient 21 June 2013 в 15:20
поделиться
  • 1
    Как это разрешает пустой путь к корректному расположению? I' m очень запутанный относительно того, как это решает использовать SiteLayoutComponent вместо AppLayoutComponent. – dlarkin77 14 February 2018 в 09:55

Если у Вас есть Повышение затем с помощью BOOST_STATIC_ASSERT, способ пойти. Если Вы используете C или не хотите добираться, Повышение вот мой c_assert.h файл, который определяет (и объясняет работы), некоторые макросы для обработки статических утверждений.

Это является немного более замысловатым, которым это должно быть, потому что в ANSI C кодируют Вас, нуждаются в 2 различных макросах - тот, который может работать в области, где у Вас есть объявления и то, которое может работать в области, куда нормальные операторы идут. Существует также немного работы, которая входит в создание макро-работы над глобальной областью видимости или в области действия блока и наборе месива, чтобы гарантировать, что нет никаких коллизий имени.

STATIC_ASSERT() может использоваться в области действия блока объявления переменной или глобальной области видимости.

STATIC_ASSERT_EX() может быть среди регулярных операторов.

Для кода C++ (или кода C99, которые позволяют объявления, смешанные с операторами) STATIC_ASSERT() будет работать где угодно.

/*
    Define macros to allow compile-time assertions.

    If the expression is false, an error something like

        test.c(9) : error XXXXX: negative subscript

    will be issued (the exact error and its format is dependent
    on the compiler).

    The techique used for C is to declare an extern (which can be used in
    file or block scope) array with a size of 1 if the expr is TRUE and
    a size of -1 if the expr is false (which will result in a compiler error).
    A counter or line number is appended to the name to help make it unique.  
    Note that this is not a foolproof technique, but compilers are
    supposed to accept multiple identical extern declarations anyway.

    This technique doesn't work in all cases for C++ because extern declarations
    are not permitted inside classes.  To get a CPP_ASSERT(), there is an 
    implementation of something similar to Boost's BOOST_STATIC_ASSERT().  Boost's
    approach uses template specialization; when expr evaluates to 1, a typedef
    for the type 

        ::interslice::StaticAssert_test< sizeof( ::interslice::StaticAssert_failed<true>) >

    which boils down to 

        ::interslice::StaticAssert_test< 1>

    which boils down to 

        struct StaticAssert_test

    is declared. If expr is 0, the compiler will be unable to find a specialization for

        ::interslice::StaticAssert_failed<false>.

    STATIC_ASSERT() or C_ASSERT should work in either C or C++ code  (and they do the same thing)

    CPP_ASSERT is defined only for C++ code.

    Since declarations can only occur at file scope or at the start of a block in 
    standard C, the C_ASSERT() or STATIC_ASSERT() macros will only work there.  For situations
    where you want to perform compile-time asserts elsewhere, use C_ASSERT_EX() or
    STATIC_ASSERT_X() which wrap an enum declaration inside it's own block.

 */

#ifndef C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546
#define C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546

/* first some utility macros to paste a line number or counter to the end of an identifier
 * this will let us have some chance of generating names that are unique
 * there may be problems if a static assert ends up on the same line number in different headers
 * to avoid that problem in C++ use namespaces
*/

#if !defined( PASTE)
#define PASTE2( x, y) x##y
#define PASTE( x, y)  PASTE2( x, y)
#endif /* PASTE */

#if !defined( PASTE_LINE)
#define PASTE_LINE( x)    PASTE( x, __LINE__)
#endif /* PASTE_LINE */

#if!defined( PASTE_COUNTER)
#if (_MSC_VER >= 1300)      /* __COUNTER__ introduced in VS 7 (VS.NET 2002) */
    #define PASTE_COUNTER( x) PASTE( x, __COUNTER__)   /* __COUNTER__ is a an _MSC_VER >= 1300 non-Ansi extension */
#else
    #define PASTE_COUNTER( x) PASTE( x, __LINE__)      /* since there's no __COUNTER__ use __LINE__ as a more or less reasonable substitute */
#endif
#endif /* PASTE_COUNTER */



#if __cplusplus
extern "C++" {   // required in case we're included inside an extern "C" block
    namespace interslice {
        template<bool b> struct StaticAssert_failed;
        template<>       struct StaticAssert_failed<true> { enum {val = 1 }; };
        template<int x>  struct StaticAssert_test { };
    }
}
    #define CPP_ASSERT( expr) typedef ::interslice::StaticAssert_test< sizeof( ::interslice::StaticAssert_failed< (bool) (expr) >) >  PASTE_COUNTER( IntersliceStaticAssertType_)
    #define STATIC_ASSERT( expr)    CPP_ASSERT( expr)
    #define STATIC_ASSERT_EX( expr) CPP_ASSERT( expr)
#else
    #define C_ASSERT_STORAGE_CLASS extern                  /* change to typedef might be needed for some compilers? */
    #define C_ASSERT_GUID 4964f7ac50fa4661a1377e4c17509495 /* used to make sure our extern name doesn't collide with something else */
    #define STATIC_ASSERT( expr)   C_ASSERT_STORAGE_CLASS char PASTE( PASTE( c_assert_, C_ASSERT_GUID), [(expr) ? 1 : -1])
    #define STATIC_ASSERT_EX(expr) do { enum { c_assert__ = 1/((expr) ? 1 : 0) }; } while (0)
#endif /* __cplusplus */

#if !defined( C_ASSERT)  /* C_ASSERT() might be defined by winnt.h */
#define C_ASSERT( expr)    STATIC_ASSERT( expr)
#endif /* !defined( C_ASSERT) */
#define C_ASSERT_EX( expr) STATIC_ASSERT_EX( expr)



#ifdef TEST_IMPLEMENTATION
C_ASSERT( 1 < 2);
C_ASSERT( 1 < 2);

int main( )
{
    C_ASSERT( 1 < 2);
    C_ASSERT( 1 < 2);

    int x;

    x = 1 + 4;

    C_ASSERT_EX( 1 < 2);
    C_ASSERT_EX( 1 < 2);



    return( 0);
}
#endif /* TEST_IMPLEMENTATION */
#endif /* C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546 */
5
ответ дан Michael Burr 21 June 2013 в 15:20
поделиться
  • 1
    @mohamadjavadTaherian у меня была та проблема прежде. Это, вероятно, происходит, потому что Вы называете < router-outlet> </router-outlet> дважды. Но если это не так тогда я предлагаю идти через Ваше приложение из index.html на. Удостоверьтесь, что Ваша логика для рендеринга Ваших представлений имеет смысл, и Вы не повторяете ничего, чтобы заставить страницу представлять дважды. Когда я имел дело с проблемой, я закончил тем, что делал новый проект и заставил основную целевую страницу работать. Тогда я переместился в каждый компонент по одному для разыскивания его.Удачи! – wuno 15 May 2017 в 09:48

Повышение контроля статичный утверждает

11
ответ дан Christian.K 21 June 2013 в 15:20
поделиться
  • 1
    Таким образом, я полагаю, что прием в Вашем коде должен всегда перенаправлять от корневого пути: ' ' к дочернему маршруту. Таким образом, что, если I' d нравится иметь полное расположение под путем: www.example.com, но совершенно другое расположение под путем: www.example.com/login? – papaiatis 16 February 2017 в 19:23

Вы можете самокрутка, статичная утверждать, нет ли у Вас доступа к сторонней библиотеке статичным, утверждают функцию (как повышение):

#define STATIC_ASSERT(x) \
    do { \
        const static char dummy[(x)?1:-1] = {0};\
    } while(0)

оборотная сторона, конечно, что сообщение об ошибке не будет очень полезным, но по крайней мере, это даст Вам номер строки.

11
ответ дан Alex B 21 June 2013 в 15:20
поделиться
  • 1
    Я был бы рад помочь Вам. Можно ли быть более конкретными? С какой проблемой Вы сталкиваетесь? – wuno 16 February 2017 в 19:24
Другие вопросы по тегам:

Похожие вопросы: