#include <stdio.h>
int (*foo(int (*i)[]))[]
{
printf("Foo()\n");
return i;
}
int main(void)
{
int (*(*F[])(int (*)[]))[] = { &foo };
(*F)(NULL);
return 0;
}
среда, 22 мая 2019 г.
Эзотерический синтаксис С
суббота, 18 мая 2019 г.
Именованные параметры на GNU C
Компилируется на диалекте GNU языка С (можно проверить на
https://wandbox.org/ ).
https://wandbox.org/ ).
#include <stdio.h>
#include <stdbool.h>
typedef struct {
bool bIsSolt;
bool bIsPepper;
bool bIsPoison;
} SoupParams;
#define GET_OVERRIDE(dummy, ARG_1, ARG_2, ARG_3, ACTION, ...) ACTION
#define PARAM_0(...)
#define PARAM_1(ARG_1) .ARG_1
#define PARAM_2(ARG_1, ...) .ARG_1, PARAM_1(__VA_ARGS__)
#define PARAM_3(ARG_1, ...) .ARG_1, PARAM_2(__VA_ARGS__)
#define SOUP_PARAMS(...) \
GET_OVERRIDE("dummy_param", ##__VA_ARGS__, PARAM_3, PARAM_2, PARAM_1, PARAM_0)(__VA_ARGS__)
static int make_soup_raw(const SoupParams *poSoupParams_)
{
if ( !poSoupParams_ ) { return -1; }
printf(" poSoupParams_->bIsSolt = %s\n", poSoupParams_->bIsSolt ? "true" : "false");
printf(" poSoupParams_->bIsPepper = %s\n", poSoupParams_->bIsPepper ? "true" : "false");
printf(" poSoupParams_->bIsPoison = %s\n", poSoupParams_->bIsPoison ? "true" : "false");
return 0;
}
#define make_soup(...) \
( \
{ \
int nResult = -1; \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Woverride-init\"") \
nResult = make_soup_raw( \
&(SoupParams) \
{ \
.bIsSolt = false, \
.bIsPepper = false, \
.bIsPoison = false, \
SOUP_PARAMS(__VA_ARGS__) \
} \
); \
_Pragma("GCC diagnostic pop") \
nResult; \
} \
)
int main(void)
{
int nResult = 0;
printf("\n make_soup(bIsSolt = true, bIsPoison = true, bIsPepper = true): \n");
nResult = make_soup(bIsSolt = true, bIsPoison = true, bIsPepper = true);
printf(" nResult: %d\n", nResult);
printf("\n make_soup(bIsPepper = true, bIsSolt = true): \n");
nResult = make_soup(bIsPepper = true, bIsSolt = true);
printf(" nResult: %d\n", nResult);
printf("\n make_soup(bIsPoison = false): \n");
nResult = make_soup(bIsPoison = false);
printf(" nResult: %d\n", nResult);
printf("\n make_soup(): \n");
nResult = make_soup();
printf(" nResult: %d\n", nResult);
return 0;
}
вторник, 1 января 2019 г.
Типовая ошибка при сравнении signed и unsigned int
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint32_t iProtocol;
} TCN_BPDU;
#define TCN_BPDU_SIZE sizeof(TCN_BPDU)
#define SIZE_LLC_HEADER 3
/* парсер TCN BPDU пакета */
static void _parseTcnBpdu(uint8_t *paPktData_, int nSize_)
{
/*
В качестве размера nSize_ приходит отрицательное число (-1), signed int.
Под определением TCN_BPDU_SIZE скрывается результат работы функции sizeof(..),
то есть 'size_t' - unsigned long int.
При операции сравнения unsigned long int и signed int,
будет приведение signed значения к unsigned значению.
То есть:
nSize_ = -1 => nSize_ = (unsigned long int) -1 = 4294967295
Поэтому, казалось бы:
if ( nSize_ < TCN_BPDU_SIZE ) { return; } => if ( -1 < 4 ) { return; }
Но фактически:
if ( nSize_ < TCN_BPDU_SIZE ) { return; } => if ( 4294967295 < 4 ) { return; };
Результат: ЗАЩИТА НЕ ОТРАБОТАЕТ
*/
if ( nSize_ < TCN_BPDU_SIZE ) {
printf("THIS IS NOT TCN_BPDU\n");
return;
}
printf("THIS IS TCN_BPDU\n");
}
/* обработчик приема пакета */
static void _receiveHandler(uint8_t *psBufRaw_, int nSize_)
{
/*
Мы знаем, что к нам приходит пакет с LLC header-ом,
поэтому 'смело' смещаем указатель и уменьшаем размер данных
на размер LLC header-а.
И совершаем ошибку - так как размер пакета меньше размера LLC header-а,
получаем отрицательную длину данных.
*/
_parseTcnBpdu(psBufRaw + SIZE_LLC_HEADER, nSize - SIZE_LLC_HEADER);
}
int main(void)
{
uint8_t aBuf[] = { 1, 2 };
_receiveHandler(aBuf, sizeof(aBuf));
return 0;
}
Подписаться на:
Комментарии (Atom)