#cpp
Day 7.
Вчера мы писали макросы, которые заменяли собой один statement. А что, если я хочу что-то более сложное?
Обопрусь на пример от Паши (https://xn--r1a.website/cpp_durka/23): напишем макрос для инкремента двух переменных.
Тут мы умные. Сразу взяли выражения в скобки. Не поставили в конце
Но если мы чуть-чуть отступим от глупого использования:
мы получим
Или ещё пример:
Тут
Канонический способ такое исправить:
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
Day 7.
Вчера мы писали макросы, которые заменяли собой один statement. А что, если я хочу что-то более сложное?
Обопрусь на пример от Паши (https://xn--r1a.website/cpp_durka/23): напишем макрос для инкремента двух переменных.
#define INCREMENT_BOTH(x, y) (x)++; (y)++
Тут мы умные. Сразу взяли выражения в скобки. Не поставили в конце
; , чтобы обязать пользователя её поставить самому (для консистентности кода). Но если мы чуть-чуть отступим от глупого использования:
if (condition)
INCREMENT_BOTH(a, b);
мы получим
if (condition)
(a)++; (b)++;
b инкрементится вне зависимости от условия. Или ещё пример:
#define MACRO(condition, x) if (condition) std::cout << (x)
if (flag)
MACRO(flag2, 5);
else
std::cout << 10;
Тут
else вдруг начинает относиться к if из макроса, а не изначальному, что очевидно баг. Канонический способ такое исправить:
#define INCREMENT_BOTH(x, y) \
do { \
(x)++; \
(y)++; \
} while (0)
#define MACRO(condition, x) \
do { \
if (condition) { \
std::cout << (x);\
} \
} while (0)
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
👍32❤1
#cpp
Day 8.
В C тоже есть массивы. И работягам тоже хочется знать, сколько в этих массивах элементов. Стандартного решения у ребят там нет, но есть общий подход, перетекающий из кодовой базы в кодовую базу. Зовётся
Выглядит так:
Тут мы полагаемся на
Так что
На собесах могут спрашивать вопросы с подвохом вида:
Конечно, вы на такое не попадётесь и скажете 10, ведь
Конечно нет!
Если ваш аргумент — Variable Length Array, то sizeof придётся вычислить аргумент. Мы можем запруфать это через наличие сайдэффекта:
Увидим called в output.https://godbolt.org/z/8G1soa8T1
Теперь срочно требуйте оффер х3 от вашего текущего дохода, ведь собеседующий почти наверняка этого не знает.
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
Day 8.
В C тоже есть массивы. И работягам тоже хочется знать, сколько в этих массивах элементов. Стандартного решения у ребят там нет, но есть общий подход, перетекающий из кодовой базы в кодовую базу. Зовётся
ARRAY_LENGTH/ARRAY_LEN/ARRAY_SIZE/COUNTOF/...Выглядит так:
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
Тут мы полагаемся на
sizeof, который, согласно стандарту C99 (моя вольная интерпретация):sizeofвозвращает размер операнда (в байтах). Размер зависит от типа операнда. Результат —int. Обычно результат не evaluated и является integer constant.
Another use of the sizeof operator is to compute the number of elements in an array:
sizeof array / sizeof array[0]
Так что
sizeof(x) вернёт кол-во байт типа массива (если x — массив int[3], то можем получить (в зависимости от системы) 12). sizeof((x)[0]) вернёт размер типа одного элемента (в нашем случае 4). Вот и получаем 3.На собесах могут спрашивать вопросы с подвохом вида:
int x = 10;
sizeof(x++);
std::cout << x; // result?
Конечно, вы на такое не попадётесь и скажете 10, ведь
sizeof интересует тип. Он не evaluatит свой аргумент. Но всегда ли это так? Если ваш аргумент — Variable Length Array, то sizeof придётся вычислить аргумент. Мы можем запруфать это через наличие сайдэффекта:
int f() {
printf("called\n");
return 10;
}
int main() {
sizeof(int[f()]);
}
Увидим called в output.
Теперь срочно требуйте оффер х3 от вашего текущего дохода, ведь собеседующий почти наверняка этого не знает.
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
👍21🔥9❤6🤯3😭2
#cpp
Day 9.
До сегодняшнего дня мы были где-то на уровне 1. Сегодня делаем шаг на следующую ступеньку (вниз или вверх, это как посмотреть).
Подстановка макросов (expansion) не являются рекурсивной.
Выстрелить себе в ногу становиться чуть сложнее. Или проще. Это опять как посмотреть.
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
Day 9.
До сегодняшнего дня мы были где-то на уровне 1. Сегодня делаем шаг на следующую ступеньку (вниз или вверх, это как посмотреть).
Подстановка макросов (expansion) не являются рекурсивной.
#define A(x) A(x x)
A(x) // A(x x)
#define B(x) C(x x)
#define C(x) B(x x)
B(x) // B(x x x x)
Выстрелить себе в ногу становиться чуть сложнее. Или проще. Это опять как посмотреть.
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
❤11👍9🔥1