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

[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
- Chapaev
- Новичок
- Сообщения: 96
- Зарегистрирован: Вт июн 19, 2001 4:01 am
- Откуда: Canada
[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]
А теперь представьте, что строк не две, а больше. Т.е. решение с запятой по тем или иным причинам не работает...[/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
О!
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]
И вот тут, к сожалению, ни запятую, ни арифметику применять нельзя - просто вот такое волюнтаристское ограничение...
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
-
- Уже с Приветом
- Сообщения: 1009
- Зарегистрирован: Вс сен 16, 2001 4:01 am
- Откуда: USA
[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]"
А теперь представьте, что строк не две, а больше. Т.е. решение с запятой по тем или иным причинам не работает...[/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 раз.
-
- Уже с Приветом
- Сообщения: 1009
- Зарегистрирован: Вс сен 16, 2001 4:01 am
- Откуда: USA
[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 такие имена,
которые точно не встретятся.
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
[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).
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
Контрпример для решения с фигурными скобками:
[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 - локальные переменные в реальной жизни не пригодились...
[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
- Vlad G
- Уже с Приветом
- Сообщения: 596
- Зарегистрирован: Вс янв 20, 2002 4:01 am
- Откуда: Israel
Re: Любителям C (если такие ещё остались)...
[quote:61051e8b82="Azazello"]Заменить её макросом [/quote:61051e8b82]
Можно полюбобытствовать, а чем функция мешала? Зачем заменять ее макросом, который и область кода и область данных увеличивает. Да еще и реализация ( и сопровождение) трудное?
Я думал, чт0 в жизни такими вещами не занимаются.
Можно полюбобытствовать, а чем функция мешала? Зачем заменять ее макросом, который и область кода и область данных увеличивает. Да еще и реализация ( и сопровождение) трудное?
Я думал, чт0 в жизни такими вещами не занимаются.
- Azazello
- Уже с Приветом
- Сообщения: 3179
- Зарегистрирован: Вт июн 12, 2001 4:01 am
- Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA
Re: Любителям C (если такие ещё остались)...
[quote:0b30a0cd7f="Vlad G"][quote:0b30a0cd7f="Azazello"]Заменить её макросом [/quote:0b30a0cd7f]
Можно полюбобытствовать, а чем функция мешала? Зачем заменять ее макросом, который и область кода и область данных увеличивает. Да еще и реализация ( и сопровождение) трудное?
Я думал, чт0 в жизни такими вещами не занимаются.[/quote:0b30a0cd7f]
Когда стек бесконечный - функциям нет равных... А когда стека всего 3-4K - тогда начинаются извращения...
Можно полюбобытствовать, а чем функция мешала? Зачем заменять ее макросом, который и область кода и область данных увеличивает. Да еще и реализация ( и сопровождение) трудное?
Я думал, чт0 в жизни такими вещами не занимаются.[/quote:0b30a0cd7f]
Когда стек бесконечный - функциям нет равных... А когда стека всего 3-4K - тогда начинаются извращения...
Всё чудесатее и чудесатее... (c) Alice
- Azazello
- Уже с Приветом
- Сообщения: 3179
- Зарегистрирован: Вт июн 12, 2001 4:01 am
- Откуда: SPb,Russia->Rehovot, Israel->Cambridge, MA
Публикую решение.
[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]
[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
-
- Уже с Приветом
- Сообщения: 1009
- Зарегистрирован: Вс сен 16, 2001 4:01 am
- Откуда: USA
[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) зачем ?
чтоб загадочнее было ?
кстати, одна } пропущена
[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) зачем ?
чтоб загадочнее было ?

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