Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 06-07-2006 14:42 » |
|
случайно столкнулся с такой непоняткой: (компилятор ошибку пропускает на ура) CString txt; const char* c1; const char* c2; //тут всё нормально: c1=(const char*)txt; //а тут нипанятна :) (обратите внимание на лишний звёздочк) c2=(const char*)*txt;
под микроскопом 118: //тут всё нормально: 119: c1=(const char*)txt; 00408082 lea ecx,[ebp-14h] 00408085 call CString::operator char const * (0040e81e) 0040808A mov dword ptr [ebp-18h],eax 120: 121: //а тут нипанятна :) (обратите внимание на лишний звёздочк) 122: c2=(const char*)*txt; 0040808D lea ecx,[ebp-14h] 00408090 call CString::operator char const * (0040e81e) 00408095 movsx ecx,byte ptr [eax] 00408098 mov dword ptr [ebp-1Ch],ecx
в косячном случае добавлена команда расширения знакового бита у адреса txt - зачем? Глюк?
|
|
|
Записан
|
|
|
|
alxmobile
Гость
|
|
« Ответ #1 : 06-07-2006 17:01 » |
|
2 AllИнтересно, что скажут знатоки синтаксиса С++. Я думал, что (const char*)*txt == (const char*)(*txt) Но оказывается, (const char*)*txt == *(const char*)(txt) 2 Алексей11532Что касается команд процессора, то там расширяется не адрес, а байт по этому адресу. Вот, смотри http://alpet.hotmail.ru/amdk6/amdopt.html
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 06-07-2006 18:05 » |
|
alxmobile, про то, ЧТО там расширяется, я в курсе Команда расширяет знаковый бит при конвертации переменной а вот - зачем это тут? глюк или нет? >> Но оказывается, (const char*)*txt == *(const char*)(txt) - точно, я проверил, а с чего бы это??
|
|
« Последнее редактирование: 06-07-2006 18:10 от Алексей1153 »
|
Записан
|
|
|
|
Scorp__)
Молодой специалист
Offline
Пол:
|
|
« Ответ #3 : 06-07-2006 18:14 » |
|
Лех, это связано с тем что, как справедливо заметил alxmobile: Но оказывается, (const char*)*txt == *(const char*)(txt) Получается, что ты берешь по адресу символ, так? А char - знаковый тип, поэтому компилятор и расширил знаковый бит. То есть это не глюк, а нормальная реакция, если конечно можно назвать ее нормальной после того как он твое желание вывернул наизнанку
|
|
|
Записан
|
- А Вы сами-то верите в привидения? - Конечно, нет, - ответил лектор и медленно растаял в воздухе.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 06-07-2006 18:23 » |
|
Scorp__), во первых , ЧТО он вывернул то? Это же синтаксическая ошибка, насклько я понимаю - нельзя разыменовать txt , это не указатель. И умножить на тип тоже низя ))) во вторых - но что там расширять-то? const char - это 1 байт
|
|
|
Записан
|
|
|
|
alxmobile
Гость
|
|
« Ответ #5 : 06-07-2006 18:52 » |
|
Алексей1153в косячном случае добавлена команда расширения знакового бита у адреса txt там расширяется не адрес, а байт по этому адресу про то, ЧТО там расширяется, я в курсе Команда расширяет знаковый бит при конвертации переменной Извини, просто формулировки невнятные. А если по сути вопроса, то по-моему - баг. У меня под VC60 повторяется.
|
|
|
Записан
|
|
|
|
alxmobile
Гость
|
|
« Ответ #6 : 06-07-2006 18:58 » |
|
Алексей1153Это же синтаксическая ошибка Согласен. Тем не менее, возможно, что txt - указетель. Я имею в виду, что в переменной txt физически хринится указеткль на экземпляр класса. Но тогда всё равно странно с точки зрения синтаксиса.
|
|
|
Записан
|
|
|
|
alxmobile
Гость
|
|
« Ответ #7 : 06-07-2006 19:14 » |
|
Так: Упорядочиваю мысли и ложусь спать.
1. Операция разыменовывания имеет правое связывание, а это значит, что (const char*)*txt == (const char*)((txt)) Но это не соответствует коду
2.Согласно команд процессора, (const char*)*txt == *(const char*)(txt) Это выражение имеет тип char, но присваивается переменной char * И это уже вторая ошибка
3. И еще есть вопрос - правомерно ли разыменовывать переменную экземпляра класса. С одной стороны, в такой переменной фактически может хранится указатель. А с другой - синтаксически недопустимо равноценно использовать переменную и указатель на нее.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #8 : 06-07-2006 19:32 » |
|
пункт 3 - экземпляр невозможно разыменовать
|
|
|
Записан
|
|
|
|
alxmobile
Гость
|
|
« Ответ #9 : 06-07-2006 19:47 » |
|
Хех... уснуть не смог. Вот, полюбуйтесь: int main(int argc, char* argv[]) { CString txt; CString *txt_ptr = new CString; const char* str; char chr; str = (const char*)txt; //тут всё нормально, txt типа CString str = (const char*)*txt_ptr; // Тоже все Ок, но txt_ptr типа CString*, и отличий в коде нет str = (const char*)*txt; // Так делать не имеем права
str = (const char*)(*txt); // Конструкция соответствует предыдущей с точки зрения и синтаксиса и кода CPU
// А вот так мы читаем первый символ строки chr = *((const char*)txt); // И команда movsx отсутствует
return 0; }
14: str = (const char*)txt; //тут всё нормально, txt типа CString 00401087 lea ecx,[ebp-10h] 0040108A call CString::operator char const * (00401386) 0040108F mov dword ptr [ebp-18h],eax 15: 16: str = (const char*)*txt_ptr; // Тоже все Ок, но txt_ptr типа CString*, и отличий в коде нет 00401092 mov ecx,dword ptr [ebp-14h] 00401095 call CString::operator char const * (00401386) 0040109A mov dword ptr [ebp-18h],eax 17: 18: str = (const char*)*txt; // Так делать не имеем права 0040109D lea ecx,[ebp-10h] 004010A0 call CString::operator char const * (00401386) 004010A5 movsx edx,byte ptr [eax] 004010A8 mov dword ptr [ebp-18h],edx 19: 20: str = (const char*)(*txt); // Конструкция соответствует предыдущей с точки зрения и синтаксиса и кода CPU 004010AB lea ecx,[ebp-10h] 004010AE call CString::operator char const * (00401386) 004010B3 movsx eax,byte ptr [eax] 004010B6 mov dword ptr [ebp-18h],eax 21: 22: // А вот так мы читаем первый символ строки 23: chr = *((const char*)txt); // И команда movsx отсутствует 004010B9 lea ecx,[ebp-10h] 004010BC call CString::operator char const * (00401386) 004010C1 mov cl,byte ptr [eax] 004010C3 mov byte ptr [ebp-1Ch],cl 24: 25: return 0;
Всё, на этот раз точно буду спать
|
|
|
Записан
|
|
|
|
Scorp__)
Молодой специалист
Offline
Пол:
|
|
« Ответ #10 : 07-07-2006 08:17 » |
|
Алексей1153, я и не спорю, что это синтаксическая ошибка Но получается, что первым действием мы преобразовали тип переменной txt из CString в *CString вот так: ((const char*)txt). Вторым действием над полученным указателем (с точки зрения компилятора уже указателем) проводим разыменование *((const char*)txt). То есть получаем char - знаковый символ. Теперь полученный символ компилятору предлагается записать в char *c2. В этом месте он почему-то решил не проявлять принципиальность, а сказать: "Ну в конце концов указатель - это двойное слово, а кто я такой, чтобы мешать записать байт в двойное слово? Вот только знак надо бы сохранить" На самом деле ему надо было выругаться на последнем действии там типы слишком явно не совпадают, но видимо он был так поражен первыми, что подумал: "Наверное он знает, что делает!! " А про вывернутое наизнанку желание. Если не считать это опечаткой, то можно предположить, что программист хотел этими строчками const char* c2; //тут всё нормально: c1=(const char*)txt; //а тут нипанятна :) (обратите внимание на лишний звёздочк) c2=(const char*)*txt; добиться такого результата : Разыменовать txt, преобразовать значение в указатель на строку (как если бы txt был на самом деле массивом указателей на строки) и сохранить полученное значение в указателе на строку с2. Если бы компилятор поставил действия в таком порядке, то он тут же обнаружил бы попытку разыменования переменной txt и сказал бы что это недопустимо. Но он почему-то решил пойти своим путем
|
|
|
Записан
|
- А Вы сами-то верите в привидения? - Конечно, нет, - ответил лектор и медленно растаял в воздухе.
|
|
|
alxmobile
Гость
|
|
« Ответ #11 : 07-07-2006 11:35 » |
|
В этом месте он почему-то решил не проявлять принципиальность, а сказать: "Ну в конце концов указатель - это двойное слово, а кто я такой, чтобы мешать записать байт в двойное слово? Вот только знак надо бы сохранить"
Точно: 32: str = (char*)chr; 00401028 movsx eax,byte ptr [ebp-8] 0040102C mov dword ptr [ebp-4],eax но видимо он был так поражен первыми, что подумал: "Наверное он знает, что делает!! ""
Но он почему-то решил пойти своим путем Как человек, прям...
|
|
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #12 : 07-07-2006 13:41 » |
|
случайно столкнулся с такой непоняткой: (компилятор ошибку пропускает на ура) Подобные плохо предсказуемые случаи встречаются сплошь и рядом при использовании приведения типов в старом стиле С. Используй лучше стиль С++, его как раз во избежание подобных непоняток и ввели. P.S. Кстати, недавно пришла посылка из "Озона", книга С. Дьюхэрста "Скользкие места С++. Как избежать проблем при проектировании и компиляции ваших программ", сейчас читаю ее, как на работе свободная минутка выпадет. Раздел 40,"Приведения в старом стиле", как раз и начинается предостережением: " Не пользуйтесь приведениями в старом стиле". Полагаю, этим советом не стоит пренебрегать.
|
|
|
Записан
|
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #13 : 07-07-2006 14:43 » |
|
Я не читал все, что выше, извините если повторюсь, но это не баг. Инструкция вполне законна, т.к. здесь срабатывает перегруженный оператор CString::operator const char*().
|
|
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 07-07-2006 15:01 » |
|
Scorp__), ты ошибаешься: >> что первым действием мы преобразовали тип переменной txt из CString в *CString вот так: >> ((const char*)txt). я не приводил к указателю на CString, но использовал оператор класса CString operator LPCTSTR ( ) const; - я и не думал про приведение к указателю, просто ошибся и напечатал лишний астериск >>А про вывернутое наизнанку желание. Если не считать это опечаткой, то можно предположить, >> что программист хотел этими строчками - вот-вот , очепяталси я просто Alf, >>Подобные плохо предсказуемые случаи встречаются сплошь и рядом при использовании >> приведения типов в старом стиле С. Используй лучше стиль С++, его как раз во избежание >> подобных непоняток и ввели. - я не пользовался стилями, я их просто не знаю... А где эту книгу мона скачать?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 07-07-2006 15:02 » |
|
LP, непонятно, а как это он так срабатывает? тип ведь не указан
|
|
|
Записан
|
|
|
|
Scorp__)
Молодой специалист
Offline
Пол:
|
|
« Ответ #16 : 07-07-2006 15:25 » |
|
Алексей1153, да я же и не утверждаю, что ты это специально сделал Я просто разбираю действия компилятора, который вообще не знает ошибся ты, или это такая хитрая-прехитрая задумка. И пытаюсь ответить на вопрос: "откуда там появился movsx?". Вполне возможно, что и в моих рассуждениях кроется какая-то ошибка, даже точно потому что к указателю не типа CString*, а к указателю char*. Но сути это не меняет, как мне кажется Кстати, в каком файле реализация CString? Или хотя бы объявление? Посмотреть на этот оператор
|
|
|
Записан
|
- А Вы сами-то верите в привидения? - Конечно, нет, - ответил лектор и медленно растаял в воздухе.
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #17 : 07-07-2006 16:26 » |
|
Инструкция *txt означает применение встроенного глобального оператора разыменования operator*(char*);, т.е. что-то вроде built-in::operator(txt); //*txt
Здесь и срабатывает оператор преобразования, собственно, для этого-то он и предназначен. Вот аналогичный код. class A { public: operator const char*() { return 0; } };
int main() { A txt; *txt;//компилируется return 0; }
Это можно видеть если в Debug'e протрассировать программу по F11. В Release компилятор оптимизирует и вызова оператора преобразования не видно.
|
|
« Последнее редактирование: 06-12-2007 19:01 от Алексей1153++ »
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
alxmobile
Гость
|
|
« Ответ #18 : 07-07-2006 18:56 » |
|
LPИнструкция *txt означает применение встроенного глобального оператора разыменования operator*(char*) Весьма занимательно! Ну хорошо, пусть так. Тогда стается еще вопрос. Выражение (const char*)*txt имеет тип (char). Почему тогда компилятор молча присваивает его указателю с типом (char*)?
|
|
|
Записан
|
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #19 : 07-07-2006 19:28 » |
|
Выражение (const char*)*txt имеет тип char*, а не char. Тип char имеет выражение (*txt) и представляет собой первый символ строки, хранящейся в CString, а уже операция (const char*) преобразует char в char*, - static_cast такое бы не пропустил.
|
|
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
alxmobile
Гость
|
|
« Ответ #20 : 07-07-2006 20:02 » |
|
Тогда осталось для нас, неграмотных, расставить все точки на i: Я пройдусь по порядку. Поправьте меня, если ошибусь.
1. Конструкцию *txt компилятор правильно воспринимает, как разыменовывание указателя. Так как txt указателем не является, то происходит неявное приведение типа, согласно определенных операторов класса. 2. Так как имеется только один такой оператор, а именно (char*), то выражение *txt принимает значение первого символа в буфере txt. 3. А теперь мы сами себе делаем подлянку через приведение символа к типу (char*).
Таким образом, имеет место две ошибки: 1. Не было учтено неявное приведение типа. 2. Использовалось приведение в старом стиле.
Спасибо, LP. Кажется, теперь все понятно.
|
|
|
Записан
|
|
|
|
Scorp__)
Молодой специалист
Offline
Пол:
|
|
« Ответ #21 : 07-07-2006 20:13 » |
|
Вот блин, пока писал, уже все за меня разобрали. Ладно оставлю пост для истории Дизассемблер как мы помним говорит: 122: c2=(const char*)*txt; 0040808D lea ecx,[ebp-14h] 00408090 call CString::operator char const * (0040e81e) 00408095 movsx ecx,byte ptr [eax] 00408098 mov dword ptr [ebp-1Ch],ecx То есть после разыменования достаем байт, этот байт затем расширяем до указателя. Хотя действительно, если первые две с половиной команды - разыменование (получаем адрес массива, достаем первый байт), а вторая половина третьей команды - преобразование типа, которое было явно указано и четвертая - присваивание, то получаем, что просили. А именно (const char*)(*txt). Пожалуй в мои рассуждения действительно вкралась ошибка. Вот только странно, что при переписывании байта в двойное слово сохраняется знак. Что компилятор решил, что у нас и отрицательная область памяти есть? Или что это индекс? Вот этот момент тогда остается непонятным.
|
|
|
Записан
|
- А Вы сами-то верите в привидения? - Конечно, нет, - ответил лектор и медленно растаял в воздухе.
|
|
|
Alf
Гость
|
|
« Ответ #22 : 07-07-2006 20:23 » |
|
А где эту книгу мона скачать? Возможно, что еще нигде низя, она 2006 года издания, только вышла. Я купил ее в "Озоне" в бумажном виде. Мой коллега попросил ее на выходные отсканить, но ниасилил. Она странного формата, в развернутом виде больше формата А4, в сканер не влазит. А по одной страничке сканить парень спекся быстро, там прилично, 264 страницы. Так что или раскошеливайся на 159р., или жди, может, у кого другого терпения больше окажется...
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #23 : 07-07-2006 20:27 » |
|
Alf, ясно Может в "Питере" появится Кстати, насчёт раскошеливайся - так её заказать можно? Где?
|
|
« Последнее редактирование: 07-07-2006 20:31 от Алексей1153 »
|
Записан
|
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #25 : 07-07-2006 21:07 » |
|
пасиба, посмотрю
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #26 : 07-07-2006 23:57 » |
|
Во намутили! Мужики, вы эт серьёзно? Жаль я раньше не заметил. А посему приношу извинения, что своевременно не внёс ясность. А в чём собственно говоря ошибка? Что тут непонятно? "Как вы яхту назовёте, так она и поплывёт" (с) Преобразование типов является сложнейшей задачей современной магии А уж тем более с константными указателями. Дело в том, что в начале вызывается оператор ОБЪЕКТА CString (НЕСТАНДАРТНОГО ТИПА ДАННЫХ С++!!!) CString::operator LPCTSTR() const { return m_pchData; }
Поэтому ваще нет необходимости в кастинге. Можно просто записать: c1 = txt; Это вообще идеально - вы предоставляете объекту САМОМУ выбрать наиболее подходящий кастинг (а иначе начерта он нужен этот объект со всеми его свойствами?). В этом случае вы УЖЕ получите указатель на const char*. Но вам этого мало, вам хочется поиздеваться и следует ещё один кастинг в const char*. Компилятор не понимает, что же вы от него хотите, но делает. Он обязан подчиняться. Таким образом можно записать (я использую для наглядности переменные из Лёшкиного примера): c2=(const char*)c1; Тут всё в порядке? Или как? Или привычней записать: c2=c1; Не ну можно конечно записать, так, для уверенности: c2=(const char*)(const char*)(const char*)(const char*)c1; чтоб, значит, железно было. Компилятор и на это не обидится. И, наконец, что же означает таинственная запись c2=(const char*)*c1; ? Уже все догадались? Для тех кто не догадался подсказка: c2=(const char*)c1[0]; Конечно! Кастинг в const char* того, что лежит по указателю с1 - просто первый байт. Может не все знают, но в С++ можно записать первый элемент массива как c1[0], так и *с1. В случае с CString это будет первый байт мембера LPTSTR m_pchData. Причём даже не произойдёт обрезания данных, о чём бы неугомонный компилятор предупредил. Вы "расширяете" переменную с 8 до 32 (размер указателя на 32-битных системах) бит. Чтож ему жаловаться? На какую ошибку? Синтактическую? И всё! "Не далее, не более" (с) Ну а ответственность за суразность происходяшего лежит целиком на программере. Компилятор не должен, не обязан это проверять. А может программер ДЕЙСТВИТЕЛЬНО хранит в первом байте указатель на некий массив символов? Тогда запись: c2=(const char*)*c1; не только, НЕ ошибочна, но и единственно верная! Желаю всем приятных сновидений. ps У меня сейчас почти два часа ночи, температура 27 по Цельсию, влажность 72% и шуток я уже не понимаю. Это на тот случай, если это хорошо продуманный прикол.
|
|
« Последнее редактирование: 08-07-2006 00:01 от Джон »
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #27 : 08-07-2006 00:11 » |
|
Альф, просто так, совет (шёпотом). С цифровой камерой книжки "сканятся" на порядок быстрей. Камера (можно, например, отдолжить на время), штатив (ну или струбцина, тиски и тд, чтобы закрепить камеру), кусок чистого стекла - и размер (формат) книги уже не имеет значения. Ну конечно об освещении нужно позаботиться. А уж когда руку набьёшь - побыстрей промышленных сканеров для книжек будет. У тех много времени уходит на перелистывание (осторожничают), но до человеческих пальчиков им ещё далеко.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #28 : 08-07-2006 04:35 » |
|
Джон, нет, это не прикол был но про то, что CString в случае *txt воспринимается как (&txt)[] или (txt.GetBuffer())[0] не знал
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #29 : 08-07-2006 07:25 » |
|
Ок - насчёт прикола. Лёш, в данном КОНКРЕТНОМ случае *txt НЕ воспринимается как (&txt)[], тк слева от = у тебя стоит тип const char*, поэтому сначала будет кастинг, а уж потом *. Оператор кастинга возвращает указатель на переменную-член m_pchData, поэтому в данноом КОНКРЕТНОМ случае, это эквивалентно m_pchData[0]. В самом общем случае *txt будет означать доступ к объекту находящемуся по адресу *txt. Попробую объяснить подробней.
Оператор * перед указателем означает, что ты хочешь получить дотсуп к самому объекту.
Например у тебя есть два указателя на объекты (те же CString):
CString *pstSrc;
CString *pstTarg;
Тогда операция pstTarg = pstSrc; приведёт к тому, что у тебя скопируется указатель. Проще говоря pstTarg будет показывать на тот же объект, что и pstSrc. Для создания копии объекта необходимо вызвать оператор присваивания объекта ( типа oprator=(const &) ), запись выглядит след. образом - *pstTarg = *pstSrc; Причём заметь, в этом случае осуществляется не доступ к первому байту внутреннего буфера (те не pstSrc->GetAt(0)), а к всему объекту. Другой пример, при передачи указателя в ф-ю
void Foo(int *pnSrc) { int nTarg = *pnSrc; // копируем объект (НЕ УКАЗАТЕЛЬ) по адресу pnSrc в локальную переменную nTarg int nTarg = pnSrc; - неправильно в этом случае
.... }
void Foo(int *pnTarg) { int nSrx = .... // вычисления ... .... *pnTarg = nTarg; // копируем результаты вычислений в объект по адресу pnSrc }
Ну и тд. В случае, когда указатель является аресом первого элемента массива, соответственно получаем первый элемент массива.
int X[9];
int *pCnt = X;
while(!bStop) { int nNextPos = F1(*pCnt); pCnt+=nNextPos;
bStop = ...
И тд
Или например, использовать в случаях, за которые я люблю С++:
char *FindPosOf(char *pStr, char chNeed) { char *pPos = pStr; while((*pPos!='\0')&&(*pPos++!=chNeed)); return pPos; }
char chNeed = 'D'; const char pszSrc [] = "ABCDEFGH"; char *p = FindPosOf(pszSrc, chNeed); TRACE1("%s\n",p);
ЭТо только пример!!! Очень рекомендуется НЕ исползовать подобные записи. В больших проектах и при интимной работе их использование категорически запрещается!!!
Если немного сумбурно, или непонятно - попробую объяснить на свежую голову. А то по этой духоте и жаре пару часов сна означают вообще ничего.
|
|
« Последнее редактирование: 06-12-2007 19:11 от Алексей1153++ »
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
|