Любителям C (если такие ещё остались)...

и задачки для интервью.
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Любителям C (если такие ещё остались)...

Сообщение Azazello »

Задача:

Дана функция:

[code:1:39a2c3fb24]
int f(int a, int b)
{
if (a > b) {
printf("a = %d, b = %d\n", a, b);
}
return a + b;
}
[/code:1:39a2c3fb24]

Заменить её макросом так, чтобы код, в котором эта функция вызывается в 3456 местах, продолжал компилироваться и правильно работать без единого изменения.

Задача из жизни (только функция предельно упрощена).
Всё чудесатее и чудесатее... (c) Alice
Аватара пользователя
Chapaev
Новичок
Сообщения: 96
Зарегистрирован: Вт июн 19, 2001 4:01 am
Откуда: Canada

Re: Любителям C (если такие ещё остались)...

Сообщение Chapaev »

[quote:ad934e350b="Azazello"]Задача:

Дана функция:

[code:1:ad934e350b]
int f(int a, int b)
{
if (a > b) {
printf("a = %d, b = %d\n", a, b);
}
return a + b;
}
[/code:1:ad934e350b]

Заменить её макросом так, чтобы код, в котором эта функция вызывается в 3456 местах, продолжал компилироваться и правильно работать без единого изменения.

Задача из жизни (только функция предельно упрощена).[/quote:ad934e350b]

Остались еще :lol:

[code:1:ad934e350b]
#define F(a, b) (((a)>(b)? printf("a = %d, b = %d\n", (a), (b)): (a)), ((a) + (b)))
[/code:1:ad934e350b]
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Сообщение Azazello »

Приемлемо...
А теперь представьте, что строк не две, а больше. Т.е. решение с запятой по тем или иным причинам не работает...
Всё чудесатее и чудесатее... (c) Alice
Аватара пользователя
Chapaev
Новичок
Сообщения: 96
Зарегистрирован: Вт июн 19, 2001 4:01 am
Откуда: Canada

Сообщение Chapaev »

[quote:ec0a1414c6="Azazello"]Приемлемо...
А теперь представьте, что строк не две, а больше. Т.е. решение с запятой по тем или иным причинам не работает...[/quote:ec0a1414c6]

Ну можно и так
[code:1:ec0a1414c6]
static char debug[128];
#define F(a, b) ((a) > (b)? printf("a = %d, b = %d\n", (a), (b)) \
- sprintf(debug, "a = %d, b = %d\n", (a), (b)) + ((a) + (b)): ((a) + (b)))
[/code:1:ec0a1414c6]

...и так
[code:1:ec0a1414c6]
#define F(a, b) ((a) > (b)? printf("a = %d, b = %d\n", (a), (b)) \
- fprintf(stderr, "a = %d, b = %d\n", (a), (b)) + ((a) + (b)): ((a) + (b)))
[/code:1:ec0a1414c6]
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Сообщение Azazello »

О!
10 баллов!

А теперь следующий вариант:

[code:1:2e3f670034]
extern int L;
extern uint M;

void f(int l, uint m, char a[], int b, char c[], char d[])
{
if ((l > L) && (m & M)) {
printf("%s: %d: %s(): %s\n", a, b, c, d);
fprintf(stderr, "%s: %d: %s(): %s\n", a, b, c, d);
}
}
[/code:1:2e3f670034]

И вот тут, к сожалению, ни запятую, ни арифметику применять нельзя - просто вот такое волюнтаристское ограничение...
Всё чудесатее и чудесатее... (c) Alice
tchicago
Уже с Приветом
Сообщения: 1009
Зарегистрирован: Вс сен 16, 2001 4:01 am
Откуда: USA

Сообщение tchicago »

[quote:6d619715ee="Azazello"]Приемлемо...
А теперь представьте, что строк не две, а больше. Т.е. решение с запятой по тем или иным причинам не работает...[/quote:6d619715ee]

нет, неприемлемо. в следующем примере если бы F было
обычной функцией, печаталось бы "val=1".:

[code:1:6d619715ee]
#include <stdio.h>

#define F(a, b) (((a)>(b)? printf("a = %d, b = %d\n", (a), (b)): (a)), ((a) + (b)))

int val = 0;

int a( )
{
++val;
return 1;
}

int main( int argc, char** argv)
{
int b = F( a(), 0 );
printf( "val=%d\n", val );

return 0;
}

[/code:1:6d619715ee]

a что печататся ? :)
таким образом, приведенное решение не выполняет условие задачи
"[b:6d619715ee]и правильно работать без единого изменения[/b:6d619715ee]"
Последний раз редактировалось tchicago Сб июн 08, 2002 12:44 am, всего редактировалось 1 раз.
tchicago
Уже с Приветом
Сообщения: 1009
Зарегистрирован: Вс сен 16, 2001 4:01 am
Откуда: USA

Сообщение tchicago »

[quote:61b15c7934="Azazello"]О!
10 баллов!

А теперь следующий вариант:

[code:1:61b15c7934]
extern int L;
extern uint M;

void f(int l, uint m, char a[], int b, char c[], char d[])
{
if ((l > L) && (m & M)) {
printf("%s: %d: %s(): %s\n", a, b, c, d);
fprintf(stderr, "%s: %d: %s(): %s\n", a, b, c, d);
}
}
[/code:1:61b15c7934]

И вот тут, к сожалению, ни запятую, ни арифметику применять нельзя - просто вот такое волюнтаристское ограничение...[/quote:61b15c7934]

здесь проще, поскольку не надо возвращать значения.
вроде ничего не мешает сделать (то же ограничение, что я упоминал выше):

[code:1:61b15c7934]
#define ff( l, m, a, b, c, d ) if (((l) > L) && ((m) & M)) { \
printf("%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
fprintf(stderr, "%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
}
[/code:1:61b15c7934]

такой вариант без того ограничения:

[code:1:61b15c7934]
#define ff( l, m, _a, _b, _c, _d ) if (((l) > L) && ((m) & M)) { \
char* a=(_a); int b=(_b); char* c=(_c); char* d=(_d); \
printf("%s: %d: %s(): %s\n", a, b, c, d); \
fprintf(stderr, "%s: %d: %s(): %s\n", a, b, c, d); \
}
[/code:1:61b15c7934]

но в таком варианте локальные переменные затеняют пространство
имен основной программы, поэтому возможна ошибка компиляции или
очень трудноуловимый глюк. Но можно применить вместо a,b,c,d такие имена,
которые точно не встретятся.
Аватара пользователя
Chapaev
Новичок
Сообщения: 96
Зарегистрирован: Вт июн 19, 2001 4:01 am
Откуда: Canada

Сообщение Chapaev »

[quote:73c3f177c1="tchicago"][quote:73c3f177c1="Azazello"]О!
10 баллов!

А теперь следующий вариант:

[code:1:73c3f177c1]
extern int L;
extern uint M;

void f(int l, uint m, char a[], int b, char c[], char d[])
{
if ((l > L) && (m & M)) {
printf("%s: %d: %s(): %s\n", a, b, c, d);
fprintf(stderr, "%s: %d: %s(): %s\n", a, b, c, d);
}
}
[/code:1:73c3f177c1]

И вот тут, к сожалению, ни запятую, ни арифметику применять нельзя - просто вот такое волюнтаристское ограничение...[/quote:73c3f177c1]

здесь проще, поскольку не надо возвращать значения.
вроде ничего не мешает сделать (то же ограничение, что я упоминал выше):

[code:1:73c3f177c1]
#define ff( l, m, a, b, c, d ) if (((l) > L) && ((m) & M)) { \
printf("%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
fprintf(stderr, "%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
}
[/code:1:73c3f177c1]

такой вариант без того ограничения:

[code:1:73c3f177c1]
#define ff( l, m, _a, _b, _c, _d ) if (((l) > L) && ((m) & M)) { \
char* a=(_a); int b=(_b); char* c=(_c); char* d=(_d); \
printf("%s: %d: %s(): %s\n", a, b, c, d); \
fprintf(stderr, "%s: %d: %s(): %s\n", a, b, c, d); \
}
[/code:1:73c3f177c1]

но в таком варианте локальные переменные затеняют пространство
имен основной программы, поэтому возможна ошибка компиляции или
очень трудноуловимый глюк. Но можно применить вместо a,b,c,d такие имена,
которые точно не встретятся.[/quote:73c3f177c1]

С локальными переменными, конечно, лучше. Кроме того они убирают дефекты вышеприведенных примеров для ++ или -- аргумента.
Только с локальными переменными F(a--, ++b) будет работать как f(a--, ++b).
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Сообщение Azazello »

Контрпример для решения с фигурными скобками:
[code:1:7304be22a7]
if (condition)
f(currentLogLevel, LOG_TRACE,
__FILE__, __LINE__, __FUNCTION__, "condition holds");
else
f(currentLogLevel, LOG_TRACE,
__FILE__, __LINE__, __FUNCTION__, "condition doesn't hold");
[/code:1:7304be22a7]
Подсказка №2 - локальные переменные в реальной жизни не пригодились...
Всё чудесатее и чудесатее... (c) Alice
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Сообщение Azazello »

Глюк...
Всё чудесатее и чудесатее... (c) Alice
Аватара пользователя
Vlad G
Уже с Приветом
Сообщения: 596
Зарегистрирован: Вс янв 20, 2002 4:01 am
Откуда: Israel

Re: Любителям C (если такие ещё остались)...

Сообщение Vlad G »

[quote:61051e8b82="Azazello"]Заменить её макросом [/quote:61051e8b82]
Можно полюбобытствовать, а чем функция мешала? Зачем заменять ее макросом, который и область кода и область данных увеличивает. Да еще и реализация ( и сопровождение) трудное?
Я думал, чт0 в жизни такими вещами не занимаются.
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Re: Любителям C (если такие ещё остались)...

Сообщение Azazello »

[quote:0b30a0cd7f="Vlad G"][quote:0b30a0cd7f="Azazello"]Заменить её макросом [/quote:0b30a0cd7f]
Можно полюбобытствовать, а чем функция мешала? Зачем заменять ее макросом, который и область кода и область данных увеличивает. Да еще и реализация ( и сопровождение) трудное?
Я думал, чт0 в жизни такими вещами не занимаются.[/quote:0b30a0cd7f]
Когда стек бесконечный - функциям нет равных... А когда стека всего 3-4K - тогда начинаются извращения...
Всё чудесатее и чудесатее... (c) Alice
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Сообщение Azazello »

Публикую решение.

[code:1:615510e938]
#define f(l,m,a,b,c,d) \
do { \
if (((l) > L) && ((m) & M)) { \
printf("%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
fprintf(stderr, "%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
} \
} while (0)
[/code:1:615510e938]
Последний раз редактировалось Azazello Ср июн 12, 2002 7:58 pm, всего редактировалось 1 раз.
Всё чудесатее и чудесатее... (c) Alice
tchicago
Уже с Приветом
Сообщения: 1009
Зарегистрирован: Вс сен 16, 2001 4:01 am
Откуда: USA

Сообщение tchicago »

[quote:80264ec71d="Azazello"]Публикую решение.

[code:1:80264ec71d]
#define f(l,m,a,b,c,d) \
do { \
if (((l) > L) && ((m) & M)) { \
printf("%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
fprintf(stderr, "%s: %d: %s(): %s\n", (a), (b), (c), (d)); \
} while (0)
[/code:1:80264ec71d][/quote:80264ec71d]


oops...
а do .. while (0) зачем ?
чтоб загадочнее было ? :mrgreen:

кстати, одна } пропущена
Аватара пользователя
Azazello
Уже с Приветом
Сообщения: 3179
Зарегистрирован: Вт июн 12, 2001 4:01 am
Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA

Сообщение Azazello »

Скобочка и вправду юыла пропущена, поправил.
А do {...} while(0) - чтобы приведённый мной контрпример (if (...) f(...); else ...) компилировался. Иначе никак...
Всё чудесатее и чудесатее... (c) Alice
Ответить

Вернуться в «Головоломки»