← All posts tagged C

sany
C gnuc оказывается можно вместо #1267777 писать так:
void print(const char *const what) __attribute__((nonnull(1)));
void print(const char *const what)
{
if (what)
printf("%s\n", what);
}
это требует чтобы аргумент 1 был не 0, но, к сожалению, такие вещи как
char *b = NULL;
print(b);
__attribute__((nonnull())) уже не ловит :(
sany
C GCC интересная штука, есть функция void print(const char *what); нужно во время компиляции выдавать ошибку, если пользователь пошлет в неё невалидное значение (NULL). решение для gcc:

#include <sys/cdefs.h>
#include <stdio.h>

__errordecl (check_null, "NULL argument!");

void print(const char *const what)
{
const __uint64_t t = (__uint64_t)what;
if (__builtin_constant_p(t) && (what == NULL))
{
check_null();
return;
}
printf("%s\n", what);
}


print("text"); // всё OK
print(NULL); // не скомпилируется
sany
C Не все читали книжки по Си и не знают ничего про макросы Си. Не терпится рассказать о том, какие возможности есть у макросов на Си и как они оформляются.
Типы макросов в Си:

1) подстановки
2) процедуры
3) функции

1) подстановки используются просто для подстановки значений, например:
#define TMP_PATH "/tmp"
пример импользования в коде:
char file[] = TMP_PATH"/file.txt";

2) процедуры используются для выполнения определенных действий, например:
#define LOG(ARGS...) \
do { \
printf("log: "); \
printf(ARGS); \
printf("\n"); \
} while (0)

пример: LOG("%s, %s!", "Hello", "world");

3) функции возвращают значения, да, макросы умеют возвращать значения, например:
#define CREATE_COPY(value) \
({ \
void *ret = malloc(sizeof(value)); \
memcpy(ret, &value, sizeof(value)); \
ret; \
})

процедуры и функции заклюючаются в разные скобки:
процедуры: do { ... } while(0) — void-выражения и требуют вконце ;
функции: ({ ... }) — возвращают значение выражения, указанное последним.