Вы можете использовать метод dataframe notnull или инвертировать isnull или numpy.isnan :
In [332]: df[df.EPS.notnull()]
Out[332]:
STK_ID RPT_Date STK_ID.1 EPS cash
2 600016 20111231 600016 4.3 NaN
4 601939 20111231 601939 2.5 NaN
In [334]: df[~df.EPS.isnull()]
Out[334]:
STK_ID RPT_Date STK_ID.1 EPS cash
2 600016 20111231 600016 4.3 NaN
4 601939 20111231 601939 2.5 NaN
In [347]: df[~np.isnan(df.EPS)]
Out[347]:
STK_ID RPT_Date STK_ID.1 EPS cash
2 600016 20111231 600016 4.3 NaN
4 601939 20111231 601939 2.5 NaN
Стандарт C11 добавляет ключевое слово _Static_assert
.
Это реализовано с gcc-4.6 :
_Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */
Первый слот должен быть интегральное постоянное выражение. Второй слот - это строковый литерал, который может быть длинным (_Static_assert(0, L"assertion of doom!")
).
Следует отметить, что это также реализовано в последних версиях clang.
Я знаю, что вопрос явно упоминает gcc, но только для полноты здесь есть настройка для компиляторов Microsoft.
Использование массива с отрицательным размером typedef не убеждает cl , чтобы выплюнуть приличную ошибку. Он просто говорит error C2118: negative subscript
. В этом отношении лучше всего подходит битовая область с нулевой шириной. Поскольку это подразумевает типизацию структуры, нам действительно нужно использовать уникальные имена типов. __LINE__
не разрезает горчицу; возможно иметь COMPILE_TIME_ASSERT()
в той же строке в заголовке и исходном файле, и ваш компилятор сломается. __COUNTER__
приходит на помощь (и он был в gcc с 4.3).
#define CTASTR2(pre,post) pre ## post
#define CTASTR(pre,post) CTASTR2(pre,post)
#define STATIC_ASSERT(cond,msg) \
typedef struct { int CTASTR(static_assertion_failed_,msg) : !!(cond); } \
CTASTR(static_assertion_failed_,__COUNTER__)
Теперь
STATIC_ASSERT(sizeof(long)==7, use_another_compiler_luke)
в cl
дает:
error C2149: 'static_assertion_failed_use_another_compiler_luke': имя битового поля не может иметь нулевую ширину
blockquote>Gcc также дает понятное сообщение:
error: zero width для бит-поля 'static_assertion_failed_use_another_compiler_luke'
blockquote>
Если вы используете макрос STATIC_ASSERT () с __LINE__
, можно избежать столкновений строк между записью в файле .c и другой записью в файле заголовка, включив __INCLUDE_LEVEL__
.
Например:
/* Trickery to create a unique variable name */
#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )
#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2( X, Y )
#define BOOST_DO_JOIN2( X, Y ) X##Y
#define STATIC_ASSERT(x) typedef char \
BOOST_JOIN( BOOST_JOIN(level_,__INCLUDE_LEVEL__), \
BOOST_JOIN(_assert_on_line_,__LINE__) ) [(x) ? 1 : -1]
Я бы не рекомендовал использовать решение с помощью typedef
:
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
Объявление массива с ключевым словом typedef
НЕ гарантируется, что оно будет оцениваться во время компиляции. Например, следующий код в области блока будет компилироваться:
int invalid_value = 0;
STATIC_ASSERT(invalid_value, this_should_fail_at_compile_time_but_will_not);
Я бы рекомендовал это вместо этого (на C99):
#define STATIC_ASSERT(COND,MSG) static int static_assertion_##MSG[(COND)?1:-1]
Из-за ключевого слова static
массив будет определен во время компиляции. Обратите внимание, что это утверждение будет работать только с COND
, которые оцениваются во время компиляции. Он не будет работать (например, сбой компиляции) с условиями, основанными на значениях в памяти, таких как значения, присвоенные переменным.
Для тех из вас, кто хочет что-то действительно базовое и портативное, но не имеет доступа к функциям C ++ 11, я написал только что. Обычно используйте STATIC_ASSERT
(вы можете записать его дважды в той же функции, если хотите) и использовать GLOBAL_STATIC_ASSERT
вне функций с уникальной фразой в качестве первого параметра.
#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;
}
Объяснение : Сначала он проверяет, есть ли у вас реальное утверждение, которое вы, безусловно, захотите использовать, если оно доступно. Если вы этого не сделаете, вы получите свой pred
текст и разделите его самостоятельно. Это делает две вещи. Если он равен нулю, id est, утверждение не сработало, это приведет к делению на нулевую ошибку (арифметика вынуждена, потому что она пытается объявить массив). Если он не равен нулю, он нормализует размер массива до 1
. Поэтому, если это утверждение прошло, вы бы не захотели, чтобы он сбой в любом случае, потому что ваш предикат был оценен как -1
(недействителен) или был 232442
(массовая потеря пространства, IDK, если бы он был оптимизирован). Для STATIC_ASSERT
он завернут в фигурные скобки, что делает его блоком, который использует переменную assert
, что означает, что вы можете писать ее много раз. Он также переключает его на void
, что является известным способом избавиться от предупреждений unused variable
. Для GLOBAL_STATIC_ASSERT
вместо того, чтобы быть в блоке кода, он генерирует пространство имен. Пространства имен разрешены вне функций. Идентификатор unique
необходим, чтобы остановить любые конфликтующие определения, если вы используете этот один более одного раза.
Работал для меня на GCC и VS'12 C ++
Это работало для какого-то старого gcc. Извините, что я забыл, какая версия была:
#define _cat(x, y) x##y
#define _sassert(exp, ln)\
extern char _cat(SASSERT_, ln)[1]; \
extern char _cat(SASSERT_, ln)[exp ? 1 : 2]
#define sassert(exp) _sassert((exp), __LINE__)
//
sassert(1 == 2);
//
#148 declaration is incompatible with "char SASSERT_134[1]" (declared at line 134) main.c /test/source/controller line 134 C/C++ Problem
Классический способ использования массива:
char int_is_4_bytes_assertion[sizeof(int) == 4 ? 1 : -1];
Это работает, потому что если утверждение истинно, массив имеет размер 1, и он действителен, но если он ложный, размер -1 дает ошибка компиляции.
Большинство компиляторов покажет имя переменной и укажет на правую часть кода, где вы можете оставить возможные комментарии об утверждении.
Из Wikipedia :
#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
COMPILE_TIME_ASSERT( BOOLEAN CONDITION );
Это работает в функциональной и нефункционной области (но не внутри структур, союзов).
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
STATIC_ASSERT(1,this_should_be_true);
int main()
{
STATIC_ASSERT(1,this_should_be_true);
}
sas.c:4: error: size of array ‘static_assertion_this_should_be_true’ is negative
__LINE__
в конце имени static_assert_...
) #define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[2*(!!(COND))-1]
, который, по-видимому, работает даже на Rusty oldc cc65 (для 6502 процессора). ОБНОВЛЕНИЕ: Для полноты, вот версия с __LINE__
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1]
// token pasting madness:
#define COMPILE_TIME_ASSERT3(X,L) STATIC_ASSERT(X,static_assertion_at_line_##L)
#define COMPILE_TIME_ASSERT2(X,L) COMPILE_TIME_ASSERT3(X,L)
#define COMPILE_TIME_ASSERT(X) COMPILE_TIME_ASSERT2(X,__LINE__)
COMPILE_TIME_ASSERT(sizeof(long)==8);
int main()
{
COMPILE_TIME_ASSERT(sizeof(int)==4);
}
UPDATE2: GCC Код
GCC 4.3 (я думаю) представил атрибуты функции «ошибка» и «предупреждение». Если вызов функции с этим атрибутом не может быть устранен посредством устранения мертвого кода (или других мер), то генерируется ошибка или предупреждение. Это можно использовать для утверждения времени компиляции с описаниями ошибок, определенных пользователем. Остается определить, как они могут использоваться в области пространства имен, не прибегая к фиктивной функции:
#define CTC(X) ({ extern int __attribute__((error("assertion failure: '" #X "' not true"))) compile_time_check(); ((X)?0:compile_time_check()),0; })
// never to be called.
static void my_constraints()
{
CTC(sizeof(long)==8);
CTC(sizeof(int)==4);
}
int main()
{
}
И вот как это выглядит:
$ gcc-mp-4.5 -m32 sas.c
sas.c: In function 'myc':
sas.c:7:1: error: call to 'compile_time_check' declared with attribute error: assertion failure: `sizeof(int)==4` not true
-Og
) может быть достаточно для того, чтобы это работало и не должно мешать отладке. Можно подумать о том, чтобы статические утверждать не-op или runtime assert, если __OPTIMIZE__
(и __GNUC__
) не определено.
– Søren Løvborg
17 September 2014 в 17:39
__LINE__
в gcc 4.1.1 ... со случайным раздражением, когда два разных заголовка имеют один на той же нумерованной строке!
– M.M
11 April 2017 в 13:36
Это работает, с опцией «удалить неиспользованный». Я могу использовать одну глобальную функцию для проверки глобальных параметров.
//
#ifndef __sassert_h__
#define __sassert_h__
#define _cat(x, y) x##y
#define _sassert(exp, ln) \
extern void _cat(ASSERT_WARNING_, ln)(void); \
if(!(exp)) \
{ \
_cat(ASSERT_WARNING_, ln)(); \
}
#define sassert(exp) _sassert(exp, __LINE__)
#endif //__sassert_h__
//-----------------------------------------
static bool tab_req_set_relay(char *p_packet)
{
sassert(TXB_TX_PKT_SIZE < 3000000);
sassert(TXB_TX_PKT_SIZE >= 3000000);
...
}
//-----------------------------------------
Building target: ntank_app.elf
Invoking: Cross ARM C Linker
arm-none-eabi-gcc ...
../Sources/host_if/tab_if.c:637: undefined reference to `ASSERT_WARNING_637'
collect2: error: ld returned 1 exit status
make: *** [ntank_app.elf] Error 1
//
_Static_assert
является частью стандарта C11 и любой компилятор, поддерживающий C11, получит его. – P.P. 12 October 2014 в 21:30error: expected declaration specifiers or '...' before 'sizeof'
для строкиstatic_assert( sizeof(int) == sizeof(long int), "Error!);
(кстати, я использую C не C ++) – user10607 21 November 2014 в 07:25_Static_assert( sizeof(int) == sizeof(long int), "Error!");
На моем macine я получаю ошибку. – emsr 21 November 2014 в 15:04error: expected declaration specifiers or '...' before 'sizeof'
ANDerror: expected declaration specifiers or '...' before string constant
(он ссылается на строку"Error!"
) (также: я компилирую с -std = c11. При помещении объявления внутри функции все работает хорошо ( терпит неудачу и преуспевает, как ожидалось)) – user10607 21 November 2014 в 15:20_Static_assert
, а не C ++ ishstatic_assert
. Вам нужно `#include & lt; assert.h & gt; для получения макроса static_assert. – emsr 21 November 2014 в 15:43