Несмотря на то, что холст позволит вам установить высоту = 2147483647, когда вы начнете рисовать, ничего не произойдет
Рисование происходит только тогда, когда я возвращаю высоту до 32767
В Gcc (c) есть несколько интересных функций, которые вы можете включить, например, объявления вложенных функций и форму a?: B оператора?:, Который возвращает a, если a не ложно.
(скрытая) особенность, которая "шокировала" меня, когда я впервые увидел, касается printf. эта функция позволяет вам использовать переменные для форматирования самих спецификаторов формата. ищите код, вы увидите лучше:
#include <stdio.h>
int main() {
int a = 3;
float b = 6.412355;
printf("%.*f\n",a,b);
return 0;
}
символ * достигает этого эффекта.
C99 имеет отличную инициализацию структуры любого порядка.
struct foo{
int x;
int y;
char* name;
};
void main(){
struct foo f = { .y = 23, .name = "awesome", .x = -38 };
}
Проверка допущений во время компиляции с использованием перечислений: Глупый пример, но он может быть действительно полезен для библиотек с константами, настраиваемыми во время компиляции.
#define D 1
#define DD 2
enum CompileTimeCheck
{
MAKE_SURE_DD_IS_TWICE_D = 1/(2*(D) == (DD)),
MAKE_SURE_DD_IS_POW2 = 1/((((DD) - 1) & (DD)) == 0)
};
Конкатенация констант
Я был очень удивлен, не увидев этого уже в ответах, поскольку все известные мне компиляторы поддерживают его, но многие программисты, кажется, игнорируй это. Иногда это действительно удобно, и не только при написании макросов.
Пример использования в моем текущем коде:
У меня есть #define PATH "/ some / path /"
в файле конфигурации (на самом деле он задается файлом makefile). Теперь я хочу построить полный путь, включая имена файлов, для открытия ресурсов. Это просто:
fd = open(PATH "/file", flags);
Вместо ужасного, но очень распространенного:
char buffer[256];
snprintf(buffer, 256, "%s/file", PATH);
fd = open(buffer, flags);
Обратите внимание, что обычное ужасное решение:
Для очистки входного буфера нельзя использовать fflush (stdin)
. Правильный способ выглядит следующим образом: scanf ("% * [^ \ n]% * c")
Это приведет к удалению всего из входного буфера.
Допустим, у вас есть структура с членами одного типа:
struct Point {
float x;
float y;
float z;
};
Вы можете преобразовать ее экземпляры в указатель с плавающей точкой и использовать индексы массива:
Point a;
int sum = 0, i = 0;
for( ; i < 3; i++)
sum += ((float*)a)[i];
Довольно элементарно, но полезно при написании краткий код.
Вот три хороших примера в gcc:
__FILE__
__FUNCTION__
__LINE__
Структуры переменного размера, которые можно увидеть в библиотеках обычных преобразователей и в других местах.
struct foo { int a; int b; char b[1]; // using [0] is no longer correct // must come at end }; char *str = "abcdef"; int len = strlen(str); struct foo *bar = malloc(sizeof(foo) + len); strcpy(bar.b, str); // try and stop me!
Оберните malloc и realloc следующим образом:
#ifdef _DEBUG
#define mmalloc(bytes) malloc(bytes);printf("malloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#define mrealloc(pointer, bytes) realloc(pointer, bytes);printf("realloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#else //_DEBUG
#define mmalloc(bytes) malloc(bytes)
#define mrealloc(pointer, bytes) realloc(pointer, bytes)
Фактически, вот мой полный арсенол (BailIfNot для OO c):
#ifdef _DEBUG
#define mmalloc(bytes) malloc(bytes);printf("malloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#define mrealloc(pointer, bytes) realloc(pointer, bytes);printf("realloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#define BAILIFNOT(Node, Check) if(Node->type != Check) return 0;
#define NULLCHECK(var) if(var == NULL) setError(__FILE__, __LINE__, "Null exception", " var ", FATAL);
#define ASSERT(n) if( ! ( n ) ) { printf("<ASSERT FAILURE@%s:%d>", __FILE__, __LINE__); fflush(0); __asm("int $0x3"); }
#define TRACE(n) printf("trace: %s <%s@%d>\n", n, __FILE__, __LINE__);fflush(0);
#else //_DEBUG
#define mmalloc(bytes) malloc(bytes)
#define mrealloc(pointer, bytes) realloc(pointer, bytes)
#define BAILIFNOT(Node, Check) {}
#define NULLCHECK(var) {}
#define ASSERT(n) {}
#define TRACE(n) {}
#endif //_DEBUG
Вот пример вывода:
malloc: 12 <hash.c@298>
trace: nodeCreate <hash.c@302>
malloc: 5 <hash.c@308>
malloc: 16 <hash.c@316>
malloc: 256 <hash.c@320>
trace: dataLoadHead <hash.c@441>
malloc: 270 <hash.c@463>
malloc: 262144 <hash.c@467>
trace: dataLoadRecursive <hash.c@404>
Я только что прочитал эту статью . В нем есть некоторые «скрытые функции» C и некоторых других языков.
Объектно-ориентированные макросы C: Вам нужен конструктор (init), деструктор (dispose), равный (равный), копировальный (copy) и некоторый прототип для создания экземпляра (prototype).
С помощью объявления вам необходимо объявить постоянный прототип для копировать и выводить из. Затем вы можете сделать C_OO_NEW
. Если нужно, я могу разместить больше примеров. LibPurple - это большая объектно-ориентированная база кода C с системой обратного вызова (если вы хотите увидеть ее в использовании)
#define C_copy(to, from) to->copy(to, from)
#define true 1
#define false 0
#define C_OO_PROTOTYPE(type)\
void type##_init (struct type##_struct *my);\
void type##_dispose (struct type##_struct *my);\
char type##_equal (struct type##_struct *my, struct type##_struct *yours); \
struct type##_struct * type##_copy (struct type##_struct *my, struct type##_struct *from); \
const type type##__prototype = {type##_init, type##_dispose, type##_equal, type##_copy
#define C_OO_OVERHEAD(type)\
void (*init) (struct type##_struct *my);\
void (*dispose) (struct type##_struct *my);\
char (*equal) (struct type##_struct *my, struct type##_struct *yours); \
struct type##_struct *(*copy) (struct type##_struct *my, struct type##_struct *from);
#define C_OO_IN(ret, type, function, ...) ret (* function ) (struct type##_struct *my, __VA_ARGS__);
#define C_OO_OUT(ret, type, function, ...) ret type##_##function (struct type##_struct *my, __VA_ARGS__);
#define C_OO_PNEW(type, instance)\
instance = ( type *) malloc(sizeof( type ));\
memcpy(instance, & type##__prototype, sizeof( type ));
#define C_OO_NEW(type, instance)\
type instance;\
memcpy(&instance, & type ## __prototype, sizeof(type));
#define C_OO_DELETE(instance)\
instance->dispose(instance);\
free(instance);
#define C_OO_INIT(type) void type##_init (struct type##_struct *my){return;}
#define C_OO_DISPOSE(type) void type##_dispose (struct type##_struct *my){return;}
#define C_OO_EQUAL(type) char type##_equal (struct type##_struct *my, struct type##_struct *yours){return 0;}
#define C_OO_COPY(type) struct type##_struct * type##_copy (struct type##_struct *my, struct type##_struct *from){return 0;}
Мне нравится оператор typeof (). Он работает как sizeof () в том смысле, что разрешается во время компиляции. Вместо того, чтобы возвращать количество байтов, он возвращает тип.
Использовать NaN для связанных вычислений / возврата ошибки:
// # include
статический uint64_t iNaN = 0xFFF8000000000000;
константный двойной NaN = * (двойной *) & iNaN; // тихо NaN
Внутренняя функция может возвращать NaN в качестве флага ошибки: ее можно безопасно использовать в любых вычислениях, и результатом всегда будет NaN.
примечание: проверка на NaN сложна, поскольку NaN! = NaN ... используйте isnan (x) или выберите свой собственный.
x! = x математически правильно, если x равно NaN, но имеет тенденцию быть оптимизированным некоторыми компиляторами
Я обнаружил это только после 15 с лишним лет программирования на C:
struct SomeStruct
{
unsigned a : 5;
unsigned b : 1;
unsigned c : 7;
};
Битовые поля! Число после двоеточия - это количество битов, требуемых члену, с членами, упакованными в указанный тип, поэтому приведенное выше будет выглядеть следующим образом, если unsigned составляет 16 бит:
xxxc cccc ccba aaaa
Skizz
intptr_t для объявления переменных типа указатель. Специфичен для C99 и объявлен в stdint.h
Лямбды (например, анонимные функции) в GCC:
#define lambda(return_type, function_body) \
({ return_type fn function_body fn })
Это может использоваться как:
lambda (int, (int x, int y) { return x > y; })(1, 2)
Что раскрывается в:
({ int fn (int x, int y) { return x > y } fn; })(1, 2)
Мне нравятся __ LINE __
и __ FILE __
. См. Здесь: http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html