Serg79
|
|
« : 05-09-2006 04:17 » |
|
Я собираю данный код в Visual C++ 6.0 #include <stdio.h>
#define VALUE THREE
#if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2 #else #define DATA 3 #endif
int main() { printf("%d\n",DATA); return 0; } Я всегда думал, что в этом случае printf должна вывести на консоль 3 но у меня почему то выводит 1. Что это, глюк препроцессора или так и должно быть?
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #1 : 05-09-2006 05:14 » |
|
1. у тебя макросы ONE TWO THREE определены до точки 2. если поределены, то как? просто #define ONE или #define ONE 1
я думаю сравнение с не определённым данными всегда даёт false
|
|
|
Записан
|
Странно всё это....
|
|
|
Serg79
|
|
« Ответ #2 : 05-09-2006 05:31 » |
|
1. у тебя макросы ONE TWO THREE определены до точки 2. если поределены, то как? просто #define ONE или #define ONE 1
Я не понял, что Вы имеете в виду. Если я напишу вот так: #include <stdio.h>
#define VALUE TWO
#if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2 #else #define DATA 3 #endif
int main() { printf("%d\n",DATA); return 0; } То здравый смысл говорит, что printf выведит на консоль 2, но не тут то было, выводится обратно 1. Я так понимаю, что препроцессор не реагирует на символьные макроопределения типа ONE, TWO, THREE и т.д.. Ему надо писать наверно что то типа того: #define ONE 1 #define TWO 2 #define THREE 3
#define VALUE TWO
#if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2 #else #define DATA 3 #endif Тогда все работает нормально. Значит получается, что в макросравнениях #if нельзя сравнивать что то со строкой, а обязательно надо сравнивать с числовыми значениями. Я прав или нет?
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #3 : 05-09-2006 05:35 » |
|
Скорее всего, это был мой глюк а не препроцессора.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #4 : 05-09-2006 05:55 » |
|
Serg79, ага твой глюк просто препроцессор в директиве #if подставляет ранее заданые значения из определений ONE TWO и THREE, а не сравнивает их имена
|
|
|
Записан
|
Странно всё это....
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #5 : 05-09-2006 06:17 » |
|
Хм. Читайте директивы препроцессора в мануалах. Откуда странная уверенность в совпадении значений слов с цифрами?
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #6 : 05-09-2006 06:31 » |
|
Гром, я даже стандарт читал.
|
|
|
Записан
|
Странно всё это....
|
|
|
Serg79
|
|
« Ответ #7 : 05-09-2006 07:29 » |
|
Хм. Читайте директивы препроцессора в мануалах. Откуда странная уверенность в совпадении значений слов с цифрами?
Смысл был не втом что бы проверять цифры, а именно проверять слова: #define VALUE TWO
#if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2 #else #define DATA 3 #endifВопрос в том, будет этот код работать как ожидается (т.е. будет выполнено #define DATA 2). Ответ, нет будет всегда выполняться #define DATA 1Вот на этом можно и обжечься.
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #8 : 05-09-2006 07:36 » |
|
#define ONE "one" #define TWO "two" #defien THREE "three"
#define VALUE "two"
#define check (a) \ ( strcmp(VALUE,b) == 0 ? 1:0 )
#if check(ONE) #define DATA 1 #elif check(TWO) #define DATA 2 #else #define DATA 3 #endif
|
|
« Последнее редактирование: 05-09-2006 07:38 от Гром »
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #9 : 05-09-2006 07:37 » |
|
Опять таки, в книге С++ для чайников в разделе - диррективы препроцессора, описано довольно подробно, что такое #define.
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #10 : 05-09-2006 07:39 » |
|
Serg79, а зачем тебе это? может, что-то из мета программирования тебе поможет?
|
|
|
Записан
|
Странно всё это....
|
|
|
Serg79
|
|
« Ответ #11 : 05-09-2006 07:40 » |
|
#define ONE "one" #define TWO "two" #defien THREE "three"
#define VALUE "two"
#define check (a) \ ( strcmp(VALUE,b) == 0 ? 1:0 )
#if check(ONE) #define DATA 1 #elif check(TWO) #define DATA 2 #else #define DATA 3 #endif
Вы хотите сказать, что в дерективы препроцессора можно встраивать конструкции языка С/С++ ?
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #12 : 05-09-2006 07:42 » |
|
Гром, но там наверное ничего не написано про поведение #if в случае, когда макроопределение не определено в точке вызова #if хотя я могу и ошибкаться, редко использую подобные конструкции, предпочитаю константы и метакод.
|
|
|
Записан
|
Странно всё это....
|
|
|
Serg79
|
|
« Ответ #13 : 05-09-2006 07:43 » |
|
Только, что проверил, Ваш код не компилируется. #include <stdio.h>
#define ONE "one" #define TWO "two" #define THREE "three"
#define VALUE "two"
#define check (a) \ ( strcmp(VALUE,b) == 0 ? 1:0 )
#if check(ONE) #define DATA 1 #elif check(TWO) #define DATA 2 #else #define DATA 3 #endif
int main() { printf("%d\n",DATA); return 0; }
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #14 : 05-09-2006 07:44 » |
|
Вот что он отвечает
Compiling... main.cpp F:\C++\temp\main.cpp(7) : warning C4005: 'VALUE' : macro redefinition f:\c++\temp\main.cpp(0) : see previous definition of 'VALUE' F:\C++\temp\main.cpp(13) : warning C4067: unexpected tokens following preprocessor directive - expected a newline F:\C++\temp\main.cpp(13) : warning C4067: unexpected tokens following preprocessor directive - expected a newline F:\C++\temp\main.cpp(15) : warning C4067: unexpected tokens following preprocessor directive - expected a newline F:\C++\temp\main.cpp(15) : warning C4067: unexpected tokens following preprocessor directive - expected a newline
main.obj - 0 error(s), 5 warning(s)
Так что я думаю, Вы в этом вопросе не правы.
|
|
« Последнее редактирование: 16-12-2007 16:31 от Алексей1153++ »
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #15 : 05-09-2006 08:01 » |
|
Serg79, код в студию. что касается, того, что мы не правы, то судя по логам ты используешь не известное макроопределение в конструкции #if #elif #endif про использование srtcmp в #if, это кострукция отработать не может по той причине что результат strcmp известен не ранее этапа компиляции, а не на этапе вормирования еденицы трансляции
|
|
|
Записан
|
Странно всё это....
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #16 : 05-09-2006 08:16 » |
|
:\C++\temp\main.cpp(7) : warning C4005: 'VALUE' : macro redefinition
Мля. Такое ощущение, что я говорю с 14 летним мальчиком. Перевести можешь. У тебя Value имеет предыдущее значение до того, как ты в своем коде описал его второй раз. Используй другое.
ЛогРус - а как ты сравниш строки на препроцессорном уровне??? В таком случае - эта задача в такой постановке решения не имеет, а надо написать свою функцию сравнения строк по буквенно. В принципе на это намекалось, но как всегда в случае примитивных вопросов - думать не хотят - хотят готовое решение.
|
|
« Последнее редактирование: 16-12-2007 16:32 от Алексей1153++ »
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Serg79
|
|
« Ответ #17 : 05-09-2006 08:38 » |
|
Гром, не переходи на личности. В пылу дискусии спутал "warning" с "error". С любым может случиться.
На счет кода он 3 постами выше.
Еще раз преношу свои извинения, код компилиться но работает не так как ожидается от него.
Еще раз все проверил, что бы не попасть в просак. По идеи на экран должно быть выведенно 2. Но на самом то деле выводиться 3. Если не верите, проверте.
И еще, для проверки этих условий должен происходить вызов функции strcmp. Я привожу листинг асемблера, выданный компилятором:
; COMDAT _main _TEXT SEGMENT _main PROC NEAR ; COMDAT
; 23 : {
push ebp mov ebp, esp sub esp, 64 ; 00000040H push ebx push esi push edi lea edi, DWORD PTR [ebp-64] mov ecx, 16 ; 00000010H mov eax, -858993460 ; ccccccccH rep stosd
; 24 : printf("%d\n",DATA);
push 3 push OFFSET FLAT:??_C@_03HMFC@?$CFd?6?$AA@ ; `string' call _printf add esp, 8
; 25 : return 0;
xor eax, eax
; 26 : }
pop edi pop esi pop ebx add esp, 64 ; 00000040H cmp ebp, esp call __chkesp mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS END
Там прекрасно видно, что вызова функции strcmp не происходит. Тогда спрашивается, как препроцессор может определить равенство значений не вызывая функции strcmp, ответ никак. По этому он и подставляет значение идущее после #else.
|
|
« Последнее редактирование: 16-12-2007 16:33 от Алексей1153++ »
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #18 : 05-09-2006 09:04 » |
|
Serg79, код в студию. что касается, того, что мы не правы, то судя по логам ты используешь не известное макроопределение в конструкции #if #elif #endif про использование srtcmp в #if, это кострукция отработать не может по той причине что результат strcmp известен не ранее этапа компиляции, а не на этапе вормирования еденицы трансляции Я это и так знаю, ты это Грому объясни. Это он предлогает данное решение, при этом называя всех чайниками. На счет известных или не известных макроопределений, я от себя ничего не добавлял, просто скопировал то что предложил Гром и проверил как это работает.
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #19 : 05-09-2006 11:55 » |
|
Serg79, хорошо, пример не помог. Значит надо начинать обижать. #include "stdafx.h" #include "string.h" #include <stdio.h> #define VALUE THREE #if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2 #else #define DATA 3 #endif int main() { printf(ONE); printf("%d\n",DATA); return 0; }
Берем добавляем один только принт - printf(ONE); Получаем: C:\temp\test\test.cpp(16) : error C2065: 'ONE' : undeclared identifier Интересно, как можно уметь получать и понимать ассемблерный код и не заметить, что в изначальном коде в препроцессоре есть сравнение с неопределенной величиной, с совершенно непредсказуемым результатом. А так же непонятно, как зная ассемблер можно писать: "Смысл был не втом что бы проверять цифры, а именно проверять слова:" Т.е. видя в ассемблере раскодировку оперетора == все равно пытаться им сранивать "слова а не цифры". Оператором сравнения цифр - сравнивать слова. Все теперь понятно. Ссылка на мануалы по прежнему актуальна. Но уже не критична. Не поможет в любом случае.
|
|
« Последнее редактирование: 16-12-2007 16:34 от Алексей1153++ »
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #20 : 05-09-2006 12:10 » |
|
Гром, я не сравниваю строки в препроцессоре(не могу даже придумать такой случай), сравниваю строки вот этим std::string::operator== в компиляторе, и как уже писал избегаю макросов, strcmp, printf и еще кое-чего я думаю
|
|
|
Записан
|
Странно всё это....
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #21 : 05-09-2006 12:36 » |
|
LogRus - а я не тебе писал Тебя я спрашивал, потому, что ты пробуешь помочь человеку это делающему. Я привел пример - где надо ставить стринг компар, он тупо его скомпилил. И ежику понятно, что я код свой не копилировал - делать мне больше нечего готовую программку дяде выкладывать просто так... Это надо было понять, что вот в этих местах надо сравнит строки. Ну или как ты ответить. Ведь код явно не рабочий. И задача не имеет смысла. В принципе.
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
npak
|
|
« Ответ #22 : 05-09-2006 14:26 » |
|
Согласно стандарту языка Си, раздел 6.10.1, выражение, стоящее справа от #if, рассматриваются как целочисленное константное выражение. Все макросы раскрываются. Если после раскрытия макросов остались идентификаторы, то они заменяются на значение 0. (ISO C, Committee Draft + August 3, 1998, раздел 6.10.1, страница 135) Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers are replaced with the pp-number 0, and then each preprocessing token is converted into a token. Практически тоже самое, слово в слово, написано в стандарте Си++. Поэтому, когда препроцессор разбирает выражение VALUE == ONE, то он делает подстановку VALUE=>THREE и получает выражение THREE == ONE. Так как идентификаторы THREE и ONE не определены как имена макросов, то они заменяются на значение 0. Выражение принимает вид 0 == 0. По правилам языка Си значение этого выражения равно 1. Следовательно, выбирается первая альтернатива. Если вам надо, чтобы выбралась ветка VALUE == THREE, то необходимо определелить макросы ONE, TWO и THREE равными целочисленным константам. Например, так: #include <stdio.h>
#define ONE 1 #define TWO 2 #define THREE 3
#define VALUE THREE
#if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2 #else #define DATA 3 #endif
int main() { printf("%d\n",DATA); return 0; } В таком случае будет цепочка преобразований (VALUE == ONE) => (TREE == 1) => (3 == 1) - то, что нужно.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #23 : 06-09-2006 05:19 » |
|
npak, пришел и всё развличение испортил это я читал, про замену не определенного идентификатора нулём только пощелкал.
|
|
|
Записан
|
Странно всё это....
|
|
|
Serg79
|
|
« Ответ #24 : 06-09-2006 07:17 » |
|
Спосибо npak, я это понял еще в третьем посту. А вот за это Если после раскрытия макросов остались идентификаторы, то они заменяются на значение 0.
отдельное спасибо, теперь буду знать. И все бы давно закончилось, если бы один умный человек не предложил бы такое решение: #define ONE "one" #define TWO "two" #defien THREE "three"
#define VALUE "two"
#define check (a) \ ( strcmp(VALUE,b) == 0 ? 1:0 )
#if check(ONE) #define DATA 1 #elif check(TWO) #define DATA 2 #else #define DATA 3 #endif
На, что ему окуратно было отвеченно: Вы хотите сказать, что в дерективы препроцессора можно встраивать конструкции языка С/С++ ? После чего, его просто понесло: Мля. Такое ощущение, что я говорю с 14 летним мальчиком.
при этом, еще пытается спасти свой код Перевести можешь. У тебя Value имеет предыдущее значение до того, как ты в своем коде описал его второй раз. Используй другое.
Ему было показано, что он написал полную лажу. На что но просто отвечает: Я привел пример - где надо ставить стринг компар, он тупо его скомпилил. И ежику понятно, что я код свой не копилировал - делать мне больше нечего готовую программку дяде выкладывать просто так... Это надо было понять, что вот в этих местах надо сравнит строки. Ну или как ты ответить. Ведь код явно не рабочий. Оказывается, когда он писал свой пример, он уже знал, что пишет полную чушь. Он просто решил посмеяться над дядей. Но в конце все же делает свой умный вывод: И задача не имеет смысла. В принципе.
Если бы я знал, уважаемый Маг-чародей 3-го уровня Гром, что этот вопрос так пагубно отразиться на вашей нервной системе. Я конечно же не стал бы его задовать. По это причине, приношу вам свои самые искренние извинения.
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #25 : 06-09-2006 20:02 » |
|
Уважаемый Serg79. На вопрос: Вы хотите сказать, что в дерективы препроцессора можно встраивать конструкции языка С/С++ ? я не могу отвечать серьезно. Потому, что strcmp библиотечная функция присутствующая и в Паскале и еще в массе языков. Фраза F:\C++\temp\main.cpp(7) : warning C4005: 'VALUE' : macro redefinition означает следующее: Внимание, VALUE макрос переназначается. Это говорит о факте уже определенности в программе этого имени как макро имя. Дальше думаю отвечать не имеет смысла. На этом форуме не принято требовать разжеванные решения. У нас тут учителя не работают.
|
|
« Последнее редактирование: 16-12-2007 16:35 от Алексей1153++ »
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
npak
|
|
« Ответ #26 : 07-09-2006 07:06 » |
|
В выражениях, входящих в директивы препроцессора, использовать strcmp для сравнения значений бесполезно.
Препроцессор умеет выполнять только простейшие операции с целыми и вещественными числами. Он ничего не знает о стандартных библиотеках языков Си и Си++ и, соответственно, не умеет ими пользоваться.
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #27 : 07-09-2006 07:31 » |
|
Препроцессор умеет выполнять только простейшие операции с целыми и вещественными числами.
С вещественными числами не все поддерживают. Точно знаю, что WinAVR отказывается обрабатывать такие выражения: #define REF_IN 2.56 #define REF_POWER 5.0 #define REF 1.25
#if REF < REF_IN ... #elif REF < REF_POWER ... #else ... #endif
Выводит: ../main.h:62:5: floating constant in preprocessor expression make: *** [main.o] Error 1
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #28 : 07-09-2006 08:10 » |
|
А теперь вспоминаем, с чего все наиналось: Я собираю данный код в Visual C++ 6.0
Код: #include <stdio.h> #define VALUE THREE# if VALUE == ONE #define DATA 1 #elif VALUE == TWO #define DATA 2#else #define DATA 3#endif int main(){ printf("%d\n",DATA); return 0; }
Я всегда думал, что в этом случае printf должна вывести на консоль 3 но у меня почему то выводит 1. Что это, глюк препроцессора или так и должно быть?
В первом посте спрашивается примитивнейший вопрос. Теперь давайте зададимся другим вопросом, зачем человеку с знаниями ассемблера и знаниями такого уровня, как неумение работы прпроцессора с плавающей запятой нужно спрашивать о неработе программы, в которой не определены сравниваемые величины, т.е. ошибка на уровне начинающего ползьзователя Serg79, будь ласка, поясни, зачем ты задал вопрос, на который знаешь ответ, если судить по твоим записям потом? Теперь по теме - неправда npak, твоя. Во превых код написаный Serg79 компилируется в gnu & VisualC++ вот так: Compiling... test.cpp C:\temp\test\test.cpp(8) : fatal error C1017: invalid integer constant expression Error executing cl.exe. test.exe - 1 error(s), 0 warning(s) Это происходит ошбка на строку: #if REF < REF_IN Т.е. сравнение делать нельзя но простой #define A 0.1 вполне можно. Во вторых - неверно, что код препроцессора не умеет работать с функциями библиотек. Есть такой код: #ifdef DEBUG #define DBG_PRINT(fmt, args...) printf( fmt, ## args) #else #define DBG_PRINT(fmt, args...) #endif Прекрасно собирающийся и компилирующийся. и главное он работает вполне предсказуемо. Т.е. директивы препроцессора умеют работать с числами с плавающей запятой, и работать с библиотечными фкункциями С/С++... Уточняйте формулирвки.
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #29 : 07-09-2006 08:18 » |
|
Во вторых - неверно, что код препроцессора не умеет работать с функциями библиотек.
Есть такой код:
#ifdef DEBUG #define DBG_PRINT(fmt, args...) printf( fmt, ## args) #else #define DBG_PRINT(fmt, args...) #endif
ну вот, что ты говоришь. препроцессор в этом примере не работает с библиотечными функциями он просто ассоциирует один текст с другим и в точках обращения к DBG_PRINT от поставит или не поставит printf НО он с ними(с функциями) не работает, это не его задача у меня ощузение, что ты просто подшучиваешь
|
|
|
Записан
|
Странно всё это....
|
|
|
|