#cpp
Day 6.
Предположим, мы хотим написать макрос для возведения значения или переменной в квадрат:
В зависимости от способа использования, вы можете не получить или получить проблемы. В таком коде:
мы на самом деле получим
Что не совсем то, что вы ожидали.
Для надёжности лучше завернуть аргументы в скобки:
Но этого тоже может иногда не хватать:
Получим:
Что тоже не то, что мы ожидали. Так что адекватный макрос должен как минимум завернуть в скобки каждый отдельный аргумент + завернуть всё выражение:
Как максимум, ваш
Так что прям совсем идеально было бы сохранить результат внутри макроса и переиспользовать его. Но я не знаю, как это написать, чтобы было полностью эквивалентно функции.
Мб пора начать сворачивать с макродорожки на что-то более современное......
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
Day 6.
Предположим, мы хотим написать макрос для возведения значения или переменной в квадрат:
#define SQR(x) x * x
В зависимости от способа использования, вы можете не получить или получить проблемы. В таком коде:
int a = SQR(1 + 2);
мы на самом деле получим
int a = 1 + 2 * 1 + 2;
Что не совсем то, что вы ожидали.
Для надёжности лучше завернуть аргументы в скобки:
#define SQR(x) (x) * (x)
Но этого тоже может иногда не хватать:
#define INC(x) (x) + 1
int a = 10 / INC(1 + 1);
Получим:
int a = 10 / (1 + 1) + 1;
Что тоже не то, что мы ожидали. Так что адекватный макрос должен как минимум завернуть в скобки каждый отдельный аргумент + завернуть всё выражение:
#define SQR(x) ((x) * (x))
Как максимум, ваш
x может быть вообще-то функцией с сайд-эффектом:
int x = SQR(GetValueFromDbAndPostToKafka());
Так что прям совсем идеально было бы сохранить результат внутри макроса и переиспользовать его. Но я не знаю, как это написать, чтобы было полностью эквивалентно функции.
Мб пора начать сворачивать с макродорожки на что-то более современное......
@thisnotes. Patreon, Boosty.
Спасибо Artyom Garkavy и niki4smirn.
🔥21❤6
#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.
👍29❤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.
👍18🔥8❤5🤯2😭1