• Авторизация


Переносимый способ обработки UTF-8 строк в C++ 28-01-2010 22:08


  Текущий стандарт С++ (C++98 и C++03) не поддерживает Unicode, поэтому при обработки текста в кодировке UTF-8 возникает множество проблем. UTF-8 текст можно хранить в объекте std::string или массиве символов char*, но в этом случае стандартные средств определения количество символов в строке или перемещения итератора (указателя) на следующий или предыдущий символ в строке будут работать не корректно. Решить некоторых проблемы обработки UTF-8 строк можно, воспользовавшись «header-only» библиотекой UTF8-CPP. UTF8-CPP состоит из шаблонов функций с проверкой правильности обрабатываемых данных (эти шаблоны функции определены в пространстве имён utf8) и более быстрых, но небезопасных шаблонов функций, без проверки (определены в пространстве имён utf8::unchecked). Функции с проверкой, в случае обнаружения неправильных данных, генерируют соответственные исключения. Все исключения библиотеки являются производными от std::exception.
  Список функций из пространства имён utf8:

Функция

Описание

utf8::append

Кодирует 32 битовое представление кодовой точки (code point) в UTF-8 последовательность октетов и добавляет эту последовательность к UTF-8 строке.

utf8::next

В качестве параметра получает ссылку на итератор начала UTF-8 последовательности, возвращает 32-х битовое представление кодовой точки и перемещает итератор на начало следующей UTF-8 последовательности.

utf8::peek_next

Аналогично utf8::next, но не изменяет позицию итератора.

utf8::prior

В качестве параметра получает итератор на любой октет в UTF-8 последовательности, перемещает итератор на начало предыдущий UTF-8 последовательности, возвращает 32-х битовое представление кодовой точки. Эту функцию можно применять для нахождения начала UTF-8 последовательности, имея случайную позицию в строке.

utf8::advance

Перемещает итератор на указанное количество кодовых точек. Перемещение допустимо только в сторону увеличения итератора.

utf8::distance

Возвращает количество кодовых точек между двумя итераторами.

utf8::utf16to8

Перекодирует строку из UTF-16 в UTF-8

utf8::utf8to16

Перекодирует строку из UTF-8 в UTF-16

utf8::utf32to8

Перекодирует строку из UTF-32 в UTF-8

utf8::utf8to32

Перекодирует строку из UTF-8 в UTF-32

utf8::find_invalid

Возвращает итератор на первую найденную, неправильную, последовательность в UTF-8 строке.

utf8::is_valid

Определяет, является ли указанная последовательность октетов правильной UTF-8 строкой. Вызов функции аналогичен коду find_invalid(start, end) == end.

utf8::replace_invalid

Заменяет указным значением, в UTF-8 строке, все неправильные последовательности.

utf8::is_bom

Читать далее...
комментарии: 2 понравилось! вверх^ к полной версии
Защита программ от переполнения буфера с помощью GCC. Часть 2. Stack Smashing Protect 31-08-2009 13:05


   SSP (Stack Smashing Protector) — это расширение GCC позволяющее защитить программу от атак основных на переполнении стека. Программы написанные на языках C, C++, Obj, и Obj++ защищаются методом добавления в функции, во время компиляции, защищающего кода.

   SSP работает по следующему принципу: в пролог функции добавляется код сохраняющий сторожевую константу в стеке, а в эпилог — код сравнивающий число сохранённое в стеке со сторожевой константой, если эти числа не равны, то программа аварийно завершается. Таким образом SSP не позволяет взломщику воспользоваться уязвимостью для захвата управления (но помогает в организации DoS;) ). Сторожевая константа сохраняется выше регистра указателя базы кадра стека ebp, поэтому невозможно, при переполнении буфера, изменит адреса возврата или ebp, не затерев сторожевую константу, но остается возможность изменения значения локальных переменных. Для того чтобы невозможно было изменить значение скалярных переменных SSP изменяет порядок локальных переменных: на вершину кадра стека помещаются скалярные переменные, а массивы располагаются ниже (взломщик может переполнением одного массива изменить содержимое другого).

          
Ниже приведён код пролога для i386:

pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl %gs:20, %eax
movl %eax, -4(%ebp)


          
Эпилог для i386 выглядит так:

xorl %gs:20, %eax
jne .L33
...
.L33:
call __stack_chk_fail // выводит сообщение и завершает работу приложения

   Область хранения сторожевой константы зависит от платформы, для Linux i386 — сохраняется в сегменте GS по смещению 0x14, в Linux x86-64 — в сегменте FS по смещению 0x28. Значение сторожевой константе присваивается при старте программы в функции _guard_setup(void), которая выглядит так:

static void __attribute__ ((constructor)) __guard_setup (void)
{
unsigned char *p;
int fd;

if (__stack_chk_guard != 0)
return;

fd = open ("/dev/urandom", O_RDONLY);
if (fd != -1)
{
ssize_t size = read (fd, &__stack_chk_guard,
sizeof (__stack_chk_guard));
close (fd);
if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0)
return;
}

/* If a random generator can't be used, the protector switches the guard
to the "terminator canary". */
p = (unsigned char *) &__stack_chk_guard;
p[sizeof(__stack_chk_guard)-1] = 255;
p[sizeof(__stack_chk_guard)-2] = '\n';
p[0] = 0;
}

   Как видно из кода, значение читается из /dev/urandom, если /dev/urandom недоступно, то в качестве сторожевой константы будет использоваться число 0xff0a0000.

   SSP включается с помощью опций -fstack-protector или -fstack-protector-all. Опция -fstack-protector — добавляет защитный код только к функциям, которые содержат буфер больше 8 байт (дополнительно смотрите в документации параметр ssp-buffer-size) либо выделяют память с помощью функции alloca(). -fstack-protector-all — добавляет защищающий код во все функции.

   Для дополнительной информации смотрите:
http://en.wikipedia.org/wiki/ProPolice
ProPolice
Переполняющиеся буфера - активные средства защиты
комментарии: 0 понравилось! вверх^ к полной версии

Защита программ от переполнения буфера с помощью GCC. Часть 1. _FORTIFY_SOURCE. 13-08-2009 15:17


Единственное отличие между багом и эксплойтом — интеллект взломщика.

Разработчики OpenBSD


   Расширение _FORTIFY_SOURCE добавляет для некоторых функций из стандартной библиотеки, работающих со строками и памятью, альтернативные функции с проверкой на допустимость длинны копируемых данных. Это обеспечивает защиту от некоторых типов атак переполнения буфера, вернее не дает взломщику воспользоваться уязвимостью для получения контроля над системой, так как при обнаружении возможного переполнения программа аварийно завершается. Вот пример альтернативной функции strcpy():


сhar * __strcpy_chk (char *__restrict__ dest, const char *__restrict__ src,   size_t slen)
{
size_t len = strlen (src);
if (len >= slen)
__chk_fail ();
return memcpy (dest, src, len + 1);
}


   Переполнения буфера может определяться на стадии компиляции или во время выполнения программы, на основании количества байт до конца объекта (массива, структуры и т.д.) и длинны копируемых данных. В зависимости от ситуации компилятор выбирает какие функции использовать, обычные или с проверкой. У функций с проверкой есть дополнительный параметр, в котором компилятор указывает количество байт до конца объекта. Если во время выполнения программы в функции с проверкой обнаруживается переполнение, то управление передается функции __chk_fail() , которая выводит сообщение в stderr, и завершает работу программы.

Возможны следующие варианты:

char buf[5];

1)
memcpy (buf, foo, 5);
strcpy (buf, "abcd");
В данном случае компилятору известно, что переполнения не будет, поэтому будут использоваться функции memcpy и strcpy.

2)
memcpy (buf, foo, n);
strcpy (buf, bar);

В этой ситуации компилятору не известно, будет переполнение или нет, но он знает размер буфера buf, поэтому будут использоваться функции с проверкой __memcpy_chk и __strcpy_chk.

3)
memcpy (buf, foo, 6);
strcpy (buf, "abcde");

Тут компилятору известно, что переполнение будет, поэтому он выдаст предупреждение при компиляции, и будет использовать функции __memcpy_chk и __strcpy_chk.

4)
char *p;
memcpy (p, q, n);
strcpy (p, q);

В данной ситуации на стадии компиляции неизвестен размер буфера, и невозможно определить возможно ли переполнение, в программе будут использоваться функции memcpy и strcpy.



   Расширение доступно в версии GCC 4.0+, и включается при помощи параметров -D_FORTIFY_SOURCE=1 или -D_FORTIFY_SOURCE=2, при включённом уровне оптимизации -O1 и выше. Между -D_FORTIFY_SOURCE=1 и -D_FORTIFY_SOURCE=2 следующие различия:


1)
struct S
{
struct T
{
char buf[5];
int x;
} t;
char buf[20];
} var;

strcpy (&var.t.buf[1], "abcdefg");


   При -D_FORTIFY_SOURCE=1, переполнение не обнаруживается, так как данные не выходят за приделы объекта VAR.
   При -D_FORTIFY_SOURCE=2, компилятор выдаст предупреждение и во время выполнения, программа аварийно завершится.



2) При -D_FORTIFY_SOURCE=2, требуется, чтобы спецификатор %n находился в области памяти доступной только для чтения, если это не так то при компиляции ни какого предупреждения не будет, а при выполнении появится сообщение «*** %n in writable segment detected ***» и программа аварийно завершится. Например следующий код будет приводить к аварийному завершению программы при -D_FORTIFY_SOURCE=2:



char buf[20];
int a;

strcpy(buf, "hello%n");
printf(buf, &a);


Дополнительная информация по данной теме Сдесь
комментарии: 0 понравилось! вверх^ к полной версии
Вращение и изменения масштаба изображения с помощью мыши в Graphics View Framework 16-07-2009 23:29


   В примере картинка будет вращаться вокруг своего центра при перемещении курсора мыши (если нажата правая кнопка) и изменять масштаб, при вращении колеса (если курсор находится над картинкой). Для растрового изображения в Graphics View Framework есть специальный класс QGraphicsPixmapItem, поэтому нужно создать его потомка, и переопределить обработчики событий: wheelEvent, mousePressEvent, mouseMoveEvent. По умолчанию у QGraphicsPixmapItem начало локальной системы координат находится в верхнем левом углу, из-за чего картинка будет вращаться вокруг верхнего левого угла, а при увеличении масштаба ползти вниз. Для того чтобы перенести начало локальной системы координат в центр нужно после создания объекта QGraphicsPixmapItem вызвать функцию setOffset:

Item->setOffset(-0.5*QPointF(pixmap.width(), pixmap.height()));


   Угол на который нужно повернуть изображение при перемещении курсора мыши будет определён из формулы векторного произведения ОМ и ОМ0:





где

  М00, у0) — начальная координата мыши;

  М(х, у) — текущая координата мыши;

  О(0, 0) — центр картинки.



void PicItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if ( event->button() == Qt::RightButton )
{
lastPos = event->pos();
return;
}

QGraphicsPixmapItem::mousePressEvent(event);
}

void PicItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::RightButton)
{
qreal det = lastPos.x() * event->pos().y() - lastPos.y() * event->pos().x();
qreal mod_a = sqrt(pow(lastPos.x(), 2) + pow(lastPos.y(), 2));
qreal mod_b = sqrt(pow(event->pos().x(), 2) + pow(event->pos().y(), 2));
qreal angle = asin(det / (mod_a * mod_b)) * 180 / M_PI;

rotate(angle);
return;
}

QGraphicsPixmapItem::mouseMoveEvent(event);
}


   Изменения масштаба с помощью колеса мыши намного проще. По знаку event->delta() определяет в какую сторону было вращение колеса и соответственно увеличиваем или уменьшаем масштаб:



void PicItem::wheelEvent(QGraphicsSceneWheelEvent * event)
{
if ( hasFocus() )
{
qreal fd_xy = (event->delta() > 0)?1.01:0.99;
scale(fd_xy, fd_xy);
}
}



Еще информация по "Каркасу графического отображения" (Graphics View Framework):


http://doc.crossplatform.ru/qt/4.3.5/graphicsview.html
http://symmetrica.net/qt4/lesson4.htm


Полный исходник в архиве 3742933_rotate_zoom.rar.
комментарии: 1 понравилось! вверх^ к полной версии
Скажи Microsoft, что ты думаешь о их поисковике 28-06-2009 13:51


   C 1 июня 2009г стал доступен новый продукт жизнедеятельности M$, поисковая система Bing. И если бы не реклама на Google, я не обратил бы на него никакого внимания.

   В поисковике мне понравилось одно, в самом низу экрана есть кнопка «Отзыв», так что любой, без регистрации, может написать все что он думает про этот поисковик. По-моему это они сделали не подумав;).
комментарии: 0 понравилось! вверх^ к полной версии
Внедрение СПО в школах под угрозой 15-06-2009 23:50


"Уважаемое сообщество! Обращаюсь к вам за помощью. К сожалению, несмотря на все заявления Д.Медведева и других руководителей о поддержке курса перехода на СПО, в реальности происходит торможение, а по сути, свертывание этого процесса. ЦеСТ пытается препятствовать этому, но мы не всесильны. Даже запросы депутатов Госдумы по этому поводу не дали результата. В настоящее время происходит просто расхищение бюджетных денег, выделенных на СПО.

Подробнее об этом можно прочитать в блоге у Алексея Новодворского и у Виктора Алксниса.

На наш взгляд осталась последняя возможность - привлечь общественное внимание к этой проблеме. Именно поэтому я обращаюсь к вам за помощью и прошу принять участие в пропаганде кампании по внедрению СПО в школы. На первых порах для этого надо максимально разместить информацию о происходящем на различных форумах и в блогах.

Кстати о блогах. У кого они есть, просьба дать у себя ссылки на вышеприведенные посты, чтобы вывести их в ТОП Яндекса.

Просьба также писать о саботаже школьного проекта в блог Медведева.

Чем больше мы вместе будем об этом говорить, тем больше шансов защитить внедрение СПО. Поймите, если школьный проект провалится (к чему идет дело), то будут провалены и планы перехода нашей страны на СПО.

Вне зависимости от наших разногласий по тем или иным вопросам, сегодня самое главное спасти школьный проект. Спасем его, значит Linux в России победит!"


Это все печально, но эта информация меня не удивила. Пора наверно привыкнуть, что любой "новый курс" у нас это так же и способ разворовать деньги, а работу поручают выполнять людям, которые в деле ничего не соображают. На Руси это было всегда...:(



Обсуждение http://www.linux.org.ru/view-message.jsp?msgid=3782833&lastmod=1245104228664
комментарии: 0 понравилось! вверх^ к полной версии
Say NO to DRM! 07-06-2009 23:33


БОЛЬШОЙ БРАТ СМОТРИТ НА ТЕБЯ
Джордж Оруэлл «1984»



   Согласно Википедии «Технические средства защиты авторских прав (ТСЗАП; англ. DRM — Digital rights management, неофициально иногда Digital restrictions management) — чаще программные, реже программно-аппаратные средства, которые затрудняют создание копий защищаемых произведений (распространяемых в электронной форме), либо позволяют отследить создание таких копий.» На самом же деле DRM ограничивает свободу пользователя и отнимает право самому распоряжаться своим имуществом. С DRM не человек принимает решение в выборе плеера или какое приложение устанавливать, за него это решают большие медиа корпорации и компании типа Microsoft, Apple, Intel. DRM также ограничивает возможность создания законной копии. В итоге эта технология становится средством для монопольного захвата рынка и не добросовестной конкуренции.



  Сайт призванный организовать борьбу против DRM http://www.defectivebydesign.org/

  Еще о DRM http://telnews.ru/Baranova_Ekaterina/c35703

  Статья Что такое TCPA
комментарии: 0 понравилось! вверх^ к полной версии
КВасик: help Linux® and Mac® OS X to become an alternative to Windows® 07-06-2009 21:38


   На днях узнал про Open Source RAD среду разработки на Basic-е — KBasic. Эта RAD написана с использованием библиотеки QT и позволяет создавать приложения для Windows, MacOS X и Linux. В языке есть режим 100% совместимости с Visual Basic 6 и возможность вызывать функции из библиотек написанных на C\C++. Не смотря на мое плохое отношение к языку Basic и ограниченные знания VBA (иногда по работе приходится делать небольшие изменения в чужом, никем не поддерживаемом, коде Excel приложений) я решил посмотреть что из себя представляет эта RAD. Для Windows KBasic платный и стоит 24.95 евро, скачать можно только пробную версию в корой отключена возможность создания exe. В прочем в результате поиска в Google были найдены ссылки на программы генерирующие серийный номер, но я ими не пользовался.

   По внешнему виду о среде разработки KBasic можно сказать, что это вполне серьезный программный продукт. Эта IDE имеет вполне интуитивно понятный интерфейс, для начинающих есть возможность включить подсказки, в которых даже будет описано как переместить компонент на форму. В настройках можно русифицировать IDE, после перезагрузки среды пункты меню и подсказки будут на русском. Вместе с KBasic поставляется много примеров программ, для открытия которых в IDE есть соответствующий пункт в главном меню.

   Думаю, что разработки поспешили брать за KBasic деньги, в редакторе кода подсказки иногда не исчезают сами, почему-то в подсказках не появляется список методов объекта, например при введении «MainForm.» в списке только компоненты формы. Так же палитра компонентов содержит мало элементов управления.

   При работе с KBasic столкнулся с проблемой, если сохранить проекты в каталоги с имени кириллицей, программы не запускаются и при этом IDE ничего не сообщает о причинах.

   Скачать KBasic можно здесь.

   Статья о KBasic «KBasic: за и против».
комментарии: 3 понравилось! вверх^ к полной версии
ДАО С++ 17-05-2009 23:26


Язык C++ был придуман специально
для того, чтобы профессиональными
программистами не становились случайные люди.
Одна из легенд языка C++


   Отрывок из книги Джеффа Элджера «Библиотека программиста C++»:
«С++ — язык, который изучается постепенно. Лишь после того, как будет сделан последний шаг, разрозненные приёмы и фрагменты синтаксиса начинают складываться в общую картину. По-моему, изучение С++ чем-то напоминает подъем на лифте. Дзынь! Второй этаж. С++ — это усовершенствованный вариант С, с сильной типизацией (которую, впрочем, при желании можно обойти) и удобными комментариями //. Любой программист на С, если он не хочет подаваться в менеджеры, должен двигаться дальше… а Бьярн Страуструп (Господи, благослови его) придумал для этого отличную возможность. Дзынь! Третий этаж. С++ — хороший, хотя и не потрясающий объектно-ориентированный язык программирования. Не Smalltalk, конечно, но чего ожидать от языка, работающего с такой головокружительной скоростью? С++ — это Cobol 90-х, политически выдержанный язык, которые гарантирует финансирование вашего проекта высшим руководством. А уж если С++ достаточно часто упоминается в плане, можно надеяться на удвоение бюджета. Это тоже хорошо, потому что никто толком не умеет оценивать проекты на С++ и управлять ими. А что касается инструментария — глаза разбегаются, не правда ли? Дзынь! Последний этаж, все выходят. Но позвольте, где же «все»? Лифт почти пуст. С++ — это на самом деле не столько язык, сколько инструмент для создания ваших собственных языков. Его элегантность заключается отнюдь не в простоте (слова С++ и простота режут слух своим явным противоречием), а в его потенциальных возможностях. За каждой уродливой проблемой прячется какая-нибудь умная идиома, изящный языковой финт, благодаря которому проблема тает прямо на глазах. Проблема решается так же элегантно, как это сделал бы настоящий язык типа Smalltalk или Lisp, но при этом ваш процессор не дымится от напряжения, а на Уолл-Стрит не растут акции производителей чипов памяти. С++ — вообще не язык. Это мировоззрение или наркотик, меняющий способ мышления.»

комментарии: 0 понравилось! вверх^ к полной версии
как включить Hyper-Threading в Core 2 Duo?;) 14-05-2009 01:00


   Обнаружил, что все программы, показывающие сведения о процессоре, написанные до появления Core 2 Duo (и некоторые новые), определяют что этот процессор поддерживает технологию Hyper-Threading. Команда cat /proc/cpuinfo в Debian Lenny 5.0 также показывает поддержку HT процессором Core 2 Duo. О причинах такого поведения программ прочитал в http://www.intel.com/Assets/PDF/appnote/241618.pdf «Intel® Processor Identification and the CPUID Instruction» - бит HTT, который раньше определял поддержку HT, так же устанавливается и для многоядерных процессоров. Для определения поддержки технологий HT ядром процессора нужно дополнительно проверять значение CPUID(1).EBX[23:16], которое показывает сколько логических процессоров содержит ядро.

   Вот ещё нашёл на форуме http://www.linuxquestions.org/questions/slackware-14/how-to-enable-hyper-threading-722669/, человек даже ядро перекомпилировал, чтобы включить HT, но это ему не помогло:(.
комментарии: 1 понравилось! вверх^ к полной версии
Оценка эффективности кода C/C++ в Windows 26-04-2009 23:11


Оценка эффективности кода в Windows



    Почти всегда при разработке программ существуют несколько реализаций одного и того-же алгоритма. Часто, для оценки влияния на скорость выполнения программы той или иной оптимизации кода, нужно измерить время выполнения алгоритма до и после оптимизации. Для измерения времени работы кода в Windows, написанного на С/С++, можно воспользоваться библиотекой ETimer. У этой библиотеки есть преимущества, перед другими методами измерения времени: точность измерения времени не зависят от изменения частоты процессора в зависимости от нагрузки (технология Intel® SpeedStep или ей подобные) и на многопроцессорных (многоядерных) системах для увеличения точности измерения выполнение потока привязывается к одном процессору. Прочитать более подробно про Etimer и скачать библиотеку можно здесь:http://software.intel.com/en-us/articles/measure-code-sections-using-the-enhanced-timer.



    Пример использование библиотеки:



#include "Etimer.h"

int main(int argc, char* argv[])
{
//создать переменную типа Etime_t
//эта структура данных
//определена в файле Etimer.h.
Etime_t mtime;

//вызвать функцию EtimeInitialize
//для инициализации переменной
if ( !EtimeInitialize(&mtime) ) return -1;

//начало измерения
if (Etime(&mtime))
{
//измеряемый участок код ;)
...

//получаем время выполнения
if (Etime(&mtime))
{
printf("Выполнялось, сек = %16.13f\n",
EtimeDurationInSeconds(&mtime));
}
}

return 0;
}
комментарии: 4 понравилось! вверх^ к полной версии
Думающий и доказывающий. 30-03-2009 01:27


Все, чем мы являемся,
есть результат наших
мыслей. Оно построено
на мысли. Оно основывается
на мысли.
Будда


Когда в руках молоток, всё вокруг кажется гвоздями.
афоризм




  Интересную модель работы человеческого мозга прочёл в книге Роберта Антона Уилсона «Прометей восставший. Психология эволюции.»:

  "По замечанию д-ра Леонарда Орра, человеческий мозг ведет себя так, как если бы он состоял из двух частей: Думающего и Доказывающего.


  Думающий может думать практически обо всем. Как показала история, он может думать, что Земля покоится на спинах бесконечных черепах, или что она внутри пуста, или что она плывет в пространстве. В это верят миллионы людей (включая автора этой книги). Сравнительная религия и философия показывают, что Думающий может считать себя смертным, бессмертным, одновременно смертным и бессмертным (реинкарнационная модель) или даже несуществующим (буддизм). Он может думать, что живет в христианском, марксистском, научно-релятивистском или нацистском мире -- и это ещё далеко не все варианты. Как часто наблюдалось психиатрами и психологами (к вящей досаде их медицинских коллег), Думающий может придумать себе болезнь и даже выздоровление.


  Доказывающий -- это гораздо более простой механизм. Он работает по единственному закону: что бы ни думал Думающий, Доказывающий это доказывает.


  Вот типичный пример, породивший невероятные ужасы в этом столетии: если Думающий думает, что все евреи богаты, Доказывающий это докажет. Он найдет свидетельства в пользу того, что самый бедный еврей в самом захудалом гетто где-то прячет деньги. Подобным образом, феминистки способны верить, что все мужчины (включая голодных бродяг, которые живут на улицах) эксплуатируют всех женщин (включая английскую королеву).


  Если Думающий думает, что Солнце вращается вокруг Земли, Доказывающий услужливо организует восприятие так, чтобы оно соответствовало этой идее; если Думающий передумает и решит, что Земля вращается вокруг Солнца,
Доказывающий организует свидетельства по-новому.".


   Хоть эта модель работы мозга и сильно упрощённая, но опровергнуть её не просто:).

комментарии: 0 понравилось! вверх^ к полной версии
Бесполезные результаты грамматики С++ 25-03-2009 23:56


Я утверждаю, что система типов
и семантика С++ чище, чем
его синтаксис
Бьерн Страуструп


   Изучая грамматику С++ обнаружил, что с ее помощью можно
строить очень странные выражения, которые можно писать только в последний
день перед увольнением:). Некоторые из этих выражений приведены в программе:


#include <iostream>

int main(int argc, char* argv[])
{
int a = +-+-+-+-+10;
int b = 5*-+-+a;

std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;


{
{
{
{
10;
std::cout << "Hello;)\n";
}
}
}
}

((a > 10)?a:b) = 100;

std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;

std::cout << ((2 < 5)?a=1, b=2, a+b: 0) << std::endl;
(1 > 0)?0:throw 1;

try
{
(1 < 0)?0:throw 1;
}
catch( ... )
{
std::cout << "Exception;)\n";
}

std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
std::cout << !!!!!!!!!!!!1 << std::endl;
}

----------------------------------------------
Результата работы программы
----------------------------------------------
a = 10
b = 50
Hello;)
a = 10
b = 100
3
Exception;)
a = 1
b = 2
1
------------------------------------------------

   Выражения с несколькими унарными знаками возможны согласно правилам:




выражение-приведения =>
унарное-выражение

унарное-выражение =>
унарный-оператор выражение-приведения

унарный-оператор =>
* & + - ! ~


   Несколько вложенных "составных инструкций" возможны по
правилам:




инструкция =>
составная-инструкция

составная-инструкция =>
{ последовательность-инструкций }

последовательность-инструкций =>
инструкция


   Приводить правила грамматики позволяющие строить с "условным выражением" такие конструкции я не буду, так как их много, если кому интересно смотрите, например в [1]. А следующее выражение допустимо, потому что оно выводима с помощью правил грамматики С++ и результат применения оператора к операнду lvalue является lvalue, если это приемлемо с точки зрения логики (lvalue - это выражение, ссылающееся на какую-то непрерывную область в памяти):


   ((a > 10)?a:b) = 100;

Например, на следующее выражение компилятор будет шибко ругаться, хотя оно и верно синтаксически, так как результат "логического ИЛИ" не есть lvalue:

   (a || b) = 1;



      Литература

1. Б. Страуструп. Язык программирования С++. Специальное издание.
2. Б. Страуструп. Дизайн и эволюция С++.

комментарии: 5 понравилось! вверх^ к полной версии
Дневник whitewin 25-03-2009 14:39


Блог о многом)))
комментарии: 1 понравилось! вверх^ к полной версии