2016-01-15 4 views
2

Я хотел бы внести изменения так, как работает некоторый код, переопределив макрос, используя старое значение макроса. Однако из-за того, что макросы кажутся оцененными, это не работает для меня. То, что я хотел бы для непосредственной оценки макроса в #define, так что-то вродекак принудительно оценивать макросы в #define для c-preprocessor

#define A B 

определяет A быть значение B в момент #define, а не зависеть от переопределения B в позднее.

Этот пример работает:

// in a header somewhere, can't change this 
#define A 1 


// wrapper code to replace the number with a run-time expression 
#define OLD_A 1 
#define NEW_A 42 
#undef A 
bool flag = false; 
#define A (flag ? NEW_A : OLD_A) 


// user code, don't want to change this 
// 

#include <stdio.h> 
main() 
{ 
    flag = false; 
    printf("A is %d\n",A); 
    flag = true; 
    printf("A is %d\n",A); 
} 

Output (по назначению):

1$ ./cpptest 
A is 1 
A is 42 

Однако, если изменить определение OLD_A к A, то он не компилируется.

// in a header somewhere, can't change this 
#define A 1 


// wrapper code to replace the number with a run-time expression 
#define OLD_A A /// <------ here 
#define NEW_A 42 
#undef A 
bool flag = false; 
#define A (flag ? NEW_A : OLD_A) 


// user code, don't want to change this 
// 

#include <stdio.h> 
main() 
{ 
    flag = false; 
    printf("A is %d\n",A); 
    flag = true; 
    printf("A is %d\n",A); 
} 

Сложение терпит неудачу:

$ make cpptest 
icpc  cpptest.cpp -o cpptest 
cpptest.cpp(19): error: identifier "A" is undefined 
    printf("A is %s\n",A); 
        ^

Я понимаю, что это ужасный способ разработки кода, чтобы быть ремонтопригодны, но это патч к разовому старого выпуска, и в этом случае он делает для меня это имеет смысл, так как это требует меньших изменений в другом рабочем коде.

ответ

0

Этот ответ касается только «Почему это не работает?» часть вопроса.
Часть «Как?» вероятно, вам нужно отказаться от намерения использовать старое определение макроса; потому что я считаю, что корень проблемы.

Макросы препроцессора работают иначе, чем переменные.
Переменные имеют значение и не заботятся о том, как они его получили.
Макросы препроцессора расширены до их определения,
не значение определения на момент определения.

Так что же происходит в проблемной случае:

// in a header somewhere, can't change this 
#define A 1 

«А» определяется в «1», который игнорируется позже.

// wrapper code to replace the number with a run-time expression 
#define OLD_A A /// <------ here 

"OLD_A" определяются в "А", которая в настоящее время бы расширяться, в два этапе, на "1".

#define NEW_A 42 
#undef A 

«A» не определено, препроцессор перестает знать, что он «1».

bool flag = false; 
#define A (flag ? NEW_A : OLD_A) 

"А" определяется на "(флаг NEW_A: OLD_A)"
которая в настоящее время будет расширяться "(? Флаг NEW_A: А)",
из которых "А" (в одном путь или другой), не рекурсивно расширенный (что тоже не помогло бы).

// user code, don't want to change this 

#include <stdio.h> 
main() 
{ 
    flag = false; 
    printf("A is %d\n",A); 

Компилятор видит: 'Е ("А% г \ п", (флаг NEW_A: А));'.

flag = true; 
    printf("A is %d\n",A); 

Компилятор видит: 'Е ("А% г \ п", (флаг NEW_A: А));'.

} 

Вы пытались предварительно обработать только файл, а не компилировать?
Это приводит к поддержке моей интерпретации.
(с помощью GCC, после того как я удалил включать, который не требуется для этого эксперимента, также удалить некоторые бесполезные строки из списка):
MinGW\bin\gcc -E cpptest.cpp

bool flag = false; 

main() 
{ 
    flag = false; 
    printf("A is %d\n",(flag ? 42 : A)); 
    flag = true; 
    printf("A is %d\n",(flag ? 42 : A)); 
} 

Вы правы по поводу «ужасного дизайна», По крайней мере, по моему мнению. Но на самом деле иногда хороший дизайн предотвращается посторонними обстоятельствами. И те внешние обстоятельства часто заканчиваются «€/$/валютой по вашему выбору».
В этом случае обстоятельства проходят обход через «код с древним и очень хорошим статусом теста, который нельзя изменить». Это хорошая причина.
Возможно, вы можете убедить лиц, принимающих решения, в том, что редактирование (которое заменит текущий полностью статический макрос «A == 1» на что-то динамическое) также не учитывает это требование. Состояние теста (вероятно, основываясь, среди прочего, на охвате кода) после этого будет в значительной степени недействительным.

Смежные вопросы