Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Компактность и красота кода


Автор: drZmeu 5.2.2007, 13:17
Есть вопрос… Точнее даже предложение скидывать в этой теме свои примеры:
Что имеется в виду:
А имеется в виду преобразование допусти ERROR в 0xBAD или
DWORD ver = MAKEWORD(2,2);
WSAStartup(ver,&wsa);
В:
WSAStartup(0x0202,&wsa);

Автор: bilbobagginz 5.2.2007, 13:21
DWORD ver = MEKAWORD(2,2);
ты наверное имел в виду:
Код

DWORD ver = MAKEWORD(2,2);


и что-же по-твоему красивее и компактнее ?

Автор: Kuvaldis 5.2.2007, 13:30
ИМХО, по теме есть хорошая книжка
Керниган, Пайк "Практика программирования"

Автор: drZmeu 5.2.2007, 13:51
Я имел в виду
замену DWORD ver = MAKEWORD(2,2); на 0x0202 ...

Автор: Vyacheslav 5.2.2007, 15:07
это типа, что красиввее
Код

int a = 4* 4;

или
Код

int a = 16;

smile

Автор: V.A.KeRneL 5.2.2007, 22:37
Имхо, дело вкуса. А больше контекста (кода, в котором находится строчка/строки). Главное, в общем случае, чтобы было максимально понятно и прозрачно именно в данном конкретном случае.

Автор: drZmeu 5.2.2007, 22:52
V.A.KeRneL -> Я с тобой полностью согласен  smile 

Автор: EvgenZ 5.2.2007, 23:01
Дяденька Дьюхэрст.
Код

if(a < b)
    a = val();
else if(b < c)
    b = val();
else
    c = val();

что эквивалентно:
Код

(a < b ? a : b < c ? b: c) = val();

Автор: Sartorius 5.2.2007, 23:05
Цитата

(a < b ? a : b < c ? b: c) = val();

 Читать такое невозможно, а код порождается ИМХО такой же как в if-ах

Автор: Fixin 5.2.2007, 23:17
Получение максимально короткого, правильного и быстрого кода - все это оптимизация, которая, в конечном счете в любом случае необходима, т. к. конечного пользователя всегда интересует производительность.

Автор: zkv 5.2.2007, 23:42
Цитата(Sartorius @  5.2.2007,  23:05 Найти цитируемый пост)
а код порождается ИМХО такой же как в if-ах 

ни с кем не спорю, просто интересный, на мой взгляд, пример:
Код

    srand( (unsigned)time( NULL ) );
    int iNum = rand();

    //это компилится
    const int a = ( iNum % 2 ) ? 1 : 0;

    //это, естественно, нет
    const int b = 0;
    if( iNum % 2 )
    {
        b = 1;
    }
    else
    {
        b = 0;
    }

как считаете, насколько красиво варьировать значение константы при инициализации? Мне кажется, что это может лишь запутать код, интересно зачем тогда оставлена такая возможность? Побочный эффект?

Автор: nickless 6.2.2007, 00:49
Цитата(zkv @ 5.2.2007,  22:42)
как считаете, насколько красиво варьировать значение константы при инициализации?

Дурное дело нехитрое...  smile 
Хотя с другой стороны, может я хочу иметь случайное число, которое генерируется во время старта и не должно изменяться после этого?
Константы вообще константны тем, что их нельзя изменить после инициализации, а как их инициализируют, это дело программиста.

Автор: bilbobagginz 6.2.2007, 01:04
я могу сказать в соторону MAKEWORD(2,2), а не в сторону 0х202
что она читабельнее, и независима от платформы, т.е. более переносима.
( если оставим факт, что MAKEWORD - макро из винды )
даже более, я бы сделал вообще так:
Код

#ifdef MAKEWORD
#define MKVERSION(rel,sub) MAKEWORD((rel),(sub))
#else
#define MKVERSION(rel,sub) ((sub)+((rel)<<16)))
#endif


вот.

читабельность в 99% важнее, чем мнимая оптимальность кода на высоком языке - как Си/Си++, так как компилятор занимается оптимизацией кода. Ессно, что алгоритмически должна быть оптимальность, но не в таком направлении как здесь: и читабельный и нечитабельный код соберутся в идентичный бинарник, поэтому нет смысла код запутывать ( а потом через пару лет шаманить с бубном, пытаясь понять его )


вот вам мои 5 коп.

Автор: Vyacheslav 6.2.2007, 11:30
Цитата(bilbobagginz @  6.2.2007,  01:04 Найти цитируемый пост)
я могу сказать в соторону MAKEWORD(2,2), а не в сторону 0х202

Коллеги. Кокой вопрос здесь может идти о красоте кода, когда реальный код просто напросто подменяется его результатом, подсчитанным в "уме"? Если придерживаться этого принципа, то в идеале любая расчетная задача сначала подсчитывается в уме, а потом  вместо алгоритма просто пишем код по выводу готового ответа и заявляем:"Это очень красивый и лаконичный код" 

Автор: Voldemar2004 6.2.2007, 12:55
Цитата(Fixin @  6.2.2007,  00:17 Найти цитируемый пост)
Получение максимально короткого, правильного и быстрого кода - все это оптимизация, которая, в конечном счете в любом случае необходима, т. к. конечного пользователя всегда интересует производительность.
Современные компиляторы и так все хорошо оптимизируют. И писать надо так, чтобы код максимально легко читался (человеком).

Автор: bilbobagginz 6.2.2007, 13:13
Цитата(Vyacheslav @ 6.2.2007,  11:30)
Кокой вопрос здесь может идти о красоте кода, когда реальный код просто напросто подменяется его результатом, подсчитанным в "уме"?

не совсем понимаю о чем вы. Если я вас правильно понимаю, всё что написано в файлах, которые скармливают компилятору - и макро и процедуры и т.д. - это всё "код", и не важно подменяется ли часть его препроцессором или нет, главное, чтобы в исходной форме он был понятен читателю ( да и писателю smile ) 

Автор: Vyacheslav 6.2.2007, 14:26
Цитата(bilbobagginz @  6.2.2007,  13:13 Найти цитируемый пост)
не совсем понимаю о чем вы.

О "красоте" конкретного примера smile
Код

DWORD ver = MAKEWORD(2,2);
WSAStartup(ver,&wsa);
 
В данном случае выясняем, что делает MAKEWORD(2,2) и делаем это вместо него в уме. Результат подставляем в код 
Код

WSAStartup(0x0202,&wsa);






Автор: FelikZ 7.2.2007, 01:46
Я за:
Код

WSAStartup(MAKEWORD(2,2), &wsa);    //а здесь комментарий(если это важно)

Автор: bilbobagginz 7.2.2007, 02:04
Цитата

В данном случае выясняем, что делает MAKEWORD(2,2) и делаем это вместо него в уме. Результат подставляем

Вячеслав. извините конечно, как говорится "the beauty is in the eye of the beholder", т.е. красота - в глазах узрившего.
вы понимаете, что вы просто таким действием сказали Бьярну Страуструпу, что он полный страус ?

что-то из серии: "Бьярн, вот скажите, ну на фига было придумывать препроцессоры, макро в Си++?"

повторяю. когда вы работаете с 1 числом, которое нужно создать таким образом  его можно запомнить, и чтить. а если таких скомпонованных чисел десятки или сотни ?
для этого и придумали МАКРО.
мейкворд создаёт слово, это к версии не относится, поэтому создаём надстройку:
мейквершен. и тогда даже через 200 лет, если люди будут программировать, прочитая этот код, понятно, что данная строка:
version=MAKEVERSION(2,3)
как то создаёт число-версию.

пока.


Автор: skyboy 7.2.2007, 02:30
Цитата(bilbobagginz @  7.2.2007,  01:04 Найти цитируемый пост)
вы понимаете, что вы просто таким действием сказали Бьярну Страуструпу, что он полный страус ?

эээ... если я правильно уловил суть, вы оба - за то, чтоб не делать работу за препроцессор, создавая более запутанный и непонятный код smile только ты ещё этого не понял(что Вячеслав - соратник, а не противник)  smile 
Цитата(Fixin @  5.2.2007,  22:17 Найти цитируемый пост)
Получение максимально короткого, правильного и быстрого кода - все это оптимизация, которая, в конечном счете в любом случае необходима, т. к. конечного пользователя всегда интересует производительность. 

никто не спорит. но добиваться скорости путем проделывания работы за препроцессор, замену умножения сдвигом и т.д. - это просто какая-то мания. или фобия. особенно, когда при этом массив на 1500 элементов сортируется "пузырьком" smile

Автор: drZmeu 7.2.2007, 10:07
Sorry давайе не будем сорится  smile 
Я несупер кодер на C++ но стараюсь стать лучше...
Любые претензии в мой адрес выслушаю...
мне интересно если я делаю так:
DWORD ver=MAKEWORD(2,2);
WSAStartup(ver,&wsa);
то тут я ещё обьявляю переменную DWORD...]
А если я делаю так
WSAStartup(0x0202,&wsa);
То тут мне не приходится обьявлять эту переменную...
Код стаёт меньше... Но я незнаю что конкретно получится в .exe файле...
Если логически посудить то получится что размер должен уменьшится smile  прошу строго не ругать и поправить если что нетак =)

Автор: Vyacheslav 7.2.2007, 14:06
Цитата(bilbobagginz @  7.2.2007,  02:04 Найти цитируемый пост)
Вячеслав. извините конечно, как говорится "the beauty is in the eye of the beholder", т.е. красота - в глазах узрившего.
вы понимаете, что вы просто таким действием сказали Бьярну Страуструпу, что он полный страус ?

что-то из серии: "Бьярн, вот скажите, ну на фига было придумывать препроцессоры, макро в Си++?"

повторяю. когда вы работаете с 1 числом, которое нужно создать таким образом  его можно запомнить, и чтить. а если таких скомпонованных чисел десятки или сотни ?
для этого и придумали МАКРО.
мейкворд создаёт слово, это к версии не относится, поэтому создаём надстройку:
мейквершен. и тогда даже через 200 лет, если люди будут программировать, прочитая этот код, понятно, что данная строка:
version=MAKEVERSION(2,3)
как то создаёт число-версию.

пока.

Простите Вы топик от начала до конца прочитали? Что такое смайлики в курс?.  Что понимается под "красотой" можете сообразить? ( в кавычках ) А если в курсе нефиг читать мне нотации. 
Я тут весь топик пытаюсь доказать, что такая замена никак не тянет на красивый код. Причем подробно разъясняю свою точку зрения. А Вы мне страусом грозите. 

"пока"

Автор: Vyacheslav 7.2.2007, 14:22
Что же я считаю действительно красивым кодом, то  Вы можете судить по данному фрагменту
http://forum.vingrad.ru/index.php?showtopic=133613&view=findpost&p=1011551
Это решение мне понравилось, даже несмотря на то что я его автор smile Обычная же ситуация такова, что мне мой код перестает нравится почти сразу же как программа уходит в production. То есть тогда, когда править  можно только  код с выявленным дефектаами, а не просто непонравившиеся места.

Добавлено @ 14:28 
Цитата(bilbobagginz @  7.2.2007,  02:04 Найти цитируемый пост)
что-то из серии: "Бьярн, вот скажите, ну на фига было придумывать препроцессоры, макро в Си++ ?"

И кстати, только счас обратил внимание. А Вы сами  а Страступа читали? В смысле не последние, а первые редакции, где он  прямо говорит об нежелательности использовать макросы в С++ smile

Автор: SergeCpp 7.2.2007, 17:12
Vyacheslav, main возвращает int, вообще-то

Вот Ваш текст
Код
#include<iostream>
#include<iterator>
#include<set>
#include <algorithm>
#include <fstream>



//---------------------------------------------------------------------------
using namespace std;
#pragma argsused
int main(int argc, char* argv[])
{
     ifstream in( "ReadMe.txt" );
     multiset<string> mset;
     copy(istream_iterator<string,char>(in),  istream_iterator<string,char>(),  inserter(mset,mset.begin()));
     for(   multiset<string>::iterator i=mset.begin(); i != mset.end(); advance(i,mset.count(*i))){
        cout << *i << " " << mset.count(*i) << endl;
     }
}

А вот на такой текст мне смотреть приятнее
Код
#include <iostream>
#include <iterator>
#include <set>
#include <algorithm>
#include <fstream>

using namespace std;

int main( int, char* [] )
{
    ifstream in( "ReadMe.txt" );

    multiset< string > mset;

    copy( istream_iterator< string, char >( in ), istream_iterator< string, char >(), inserter( mset, mset.begin() ) );

    for( multiset< string >::iterator i( mset.begin() ); i != mset.end(); advance( i, mset.count( *i ) ) )
    {
        cout << *i << " " << mset.count( *i ) << endl;
    }

    return 0;
}

// EOF


P.S. Исправил multiset<string> на multiset< string > (см. вопрос ниже). Прошу извинить за невнимательность. В рабочем коде (при многочисленных просматриваниях) я бы это непременно заметил и поправил. Неудобно тут писать smile В VC6 удобнее smile А пишу я именно так. Мне так нравится.

Автор: Vyacheslav 7.2.2007, 17:45
Цитата(SergeCpp @  7.2.2007,  17:12 Найти цитируемый пост)
Vyacheslav, main возвращает int, вообще-то

Да. Это конечно очень серьезная ошибка, не спорю smile


Цитата(SergeCpp @  7.2.2007,  17:12 Найти цитируемый пост)
А вот на такой текст мне смотреть приятнее

В смысле скопировать и через строчку? Да без разницы. Раз нравится - пишите через строчку. Вопрос не в том, как располагать, а в том что поставленная задача потребовала  5 строчек кода.



Автор: skyboy 7.2.2007, 18:08
SergeCpp, скажи,  а почему в 
Цитата(SergeCpp @  7.2.2007,  16:12 Найти цитируемый пост)
multiset<string>

отступов нет, а в 
Цитата(SergeCpp @  7.2.2007,  16:12 Найти цитируемый пост)
istream_iterator< string, char >

каждый из двух типов обрамлен пробелами?
я не прикапываюсь, просто интересно smile
Цитата(Vyacheslav @  7.2.2007,  16:45 Найти цитируемый пост)
В смысле скопировать и через строчку? Да без разницы.

здесь ведь речь не об эффективности, а об эстетике, правда? а тут уже личные вкусы играют роль smile 

Автор: Любитель 7.2.2007, 19:04
Цитата(SergeCpp @  7.2.2007,  17:12 Найти цитируемый пост)
Vyacheslav, main возвращает int, вообще-то

В плюсах по стандарту main может ничего не возвращать (хотя в сигнатуре пишется int) - подразумевается 0.


Цитата(skyboy @  7.2.2007,  18:08 Найти цитируемый пост)
SergeCpp, скажи,  а почему в
Цитата(SergeCpp @  7.2.2007 @   16:12)

multiset<string>

отступов нет, а в 
Цитата(SergeCpp @  7.2.2007 @   16:12[/quote)

istream_iterator< string, char >

каждый из двух типов обрамлен пробелами?

Ну тогда почему здесь
Цитата(Vyacheslav @  5.2.2007,  15:07 Найти цитируемый пост)
Код
int a = 4* 4;

перед звёздочкой нет пробела, а после есть?  smile Просто если оптимизировать программу, так уж по полной - надо убрать и второй пробел (а то вдруг наш компилер нае поддерживате компиляцию файлов со столь большими строками  smile )

Цитата(drZmeu @  7.2.2007,  10:07 Найти цитируемый пост)
мне интересно если я делаю так:
DWORD ver=MAKEWORD(2,2);
WSAStartup(ver,&wsa);
то тут я ещё обьявляю переменную DWORD...]
А если я делаю так
WSAStartup(0x0202,&wsa);
То тут мне не приходится обьявлять эту переменную...
Код стаёт меньше... Но я незнаю что конкретно получится в .exe файле...
Если логически посудить то получится что размер должен уменьшится 

drZmeu, разочарую тебя - уж столь отривиальные случаи компилер точно сведёт в одно. Оптимизатор в современном компиляторе - очень жестокая вещь. Он мжоет перевернуть код гораздо серьёзнй (без последствий логике).

Автор: Rockie 7.2.2007, 19:24
Цитата(bilbobagginz @  6.2.2007,  01:04 Найти цитируемый пост)
читабельность в 99% важнее, чем мнимая оптимальность кода на высоком языке - как Си/Си++, так как компилятор занимается оптимизацией кода. Ессно, что алгоритмически должна быть оптимальность, но не в таком направлении как здесь: и читабельный и нечитабельный код соберутся в идентичный бинарник, поэтому нет смысла код запутывать ( а потом через пару лет шаманить с бубном, пытаясь понять его )

+1
Цитата(Любитель @  7.2.2007,  19:04 Найти цитируемый пост)
В плюсах по стандарту main может ничего не возвращать

скорее "современные компиляторы добавят return 0, если такового не имеется" 


Автор: Любитель 7.2.2007, 19:26
Можно сказать точнее - "явно ничего не возвращать".

Автор: Vyacheslav 8.2.2007, 11:25
Цитата(skyboy @  7.2.2007,  18:08 Найти цитируемый пост)
здесь ведь речь не об эффективности, а об эстетике, правда? а тут уже личные вкусы играют роль   

Ну тогда извините. Под красотой я прежде всего понимаю возможность  максимальное использование возможностей языка, а не отступы, строчки - черезстрочки. Хотя для читабельности кода это играет далеко не второстепенную роль.
И для меня одним из фрагментов, написанных на С++, который стразу приходят на ум когда говорят о красивом коде, является  фрагмент из двух строчек, помещенных в предисловии Скотта Мейерса к книге Александреску "Современное проектировние на С++"
Код

template<bool> strcut CTAssert;
template<> struct CTAssert<true>;
  


Автор: bilbobagginz 8.2.2007, 11:33
Цитата(bilbobagginz)

( а потом через пару лет шаманить с бубном, пытаясь понять его )

это я конечно загнул, для полного стирания кода из моей памяти нужно просто зкончить один проект, и перейти на другой. т.е. и пары месяцев хватает чтобы ПОЛНОСТЬЮ забыть что я там написал.

Автор: SergeCpp 8.2.2007, 12:49
Вспомнилось... Занимался я как-то извлечением механизма обработки регулярных выражений из Perl'а...

Увидел исходники...

Брался несколько раз и откладывал...

Потом как-то набрался мужества и осилил user posted image

Столько там встретил интересного user posted image

В общем, считай, заново переписал

Ужас — одно слово. Просто — ужас

Вот сейчас скачал версию 5.8.8 stable

Полюбуйтесь на файл http://rsdn.ru/File/44396/regcomp.c

Вот функция, имеющая отношение к оптимизации регулярного выражения...

Ровно 1000 строк!

Ну, чуть больше, просто в SciTE сейчас смотрю, свернул её "плюсиком",
открывающая скобка на 674 строке, а следующая за свёрнутым блоком строка — 1674 user posted image

Пусть Ларри Уоллу будет стыдно user posted image

Код
/* REx optimizer.  Converts nodes into quickier variants "in place".
   Finds fixed substrings.  */

/* Stops at toplevel WHILEM as well as at "last". At end *scanp is set
   to the position after last scanned or to NULL. */

STATIC I32
S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32 flags)
            /* scanp: Start here (read-write). */
            /* deltap: Write maxlen-minlen here. */
            /* last: Stop before this one. */
{
    I32 min = 0, pars = 0, code;
    regnode *scan = *scanp, *next;
    I32 delta = 0;
    int is_inf = (flags & SCF_DO_SUBSTR) && (data->flags & SF_IS_INF);
    int is_inf_internal = 0;        /* The studied chunk is infinite */
    I32 is_par = OP(scan) == OPEN ? ARG(scan) : 0;
    scan_data_t data_fake;
    struct regnode_charclass_class and_with; /* Valid if flags & SCF_DO_STCLASS_OR */

    while (scan && OP(scan) != END && scan < last) {
    /* Peephole optimizer: */

    if (PL_regkind[(U8)OP(scan)] == EXACT) {
        /* Merge several consecutive EXACTish nodes into one. */
        regnode *n = regnext(scan);
        U32 stringok = 1;
#ifdef DEBUGGING
        regnode *stop = scan;
#endif

        next = scan + NODE_SZ_STR(scan);
        /* Skip NOTHING, merge EXACT*. */
        while (n &&
           ( PL_regkind[(U8)OP(n)] == NOTHING ||
             (stringok && (OP(n) == OP(scan))))
           && NEXT_OFF(n)
           && NEXT_OFF(scan) + NEXT_OFF(n) < I16_MAX) {
        if (OP(n) == TAIL || n > next)
            stringok = 0;
        if (PL_regkind[(U8)OP(n)] == NOTHING) {
            NEXT_OFF(scan) += NEXT_OFF(n);
            next = n + NODE_STEP_REGNODE;
#ifdef DEBUGGING
            if (stringok)
            stop = n;
#endif
            n = regnext(n);
        }
        else if (stringok) {
            const int oldl = STR_LEN(scan);
            regnode *nnext = regnext(n);

            if (oldl + STR_LEN(n) > U8_MAX)
            break;
            NEXT_OFF(scan) += NEXT_OFF(n);
            STR_LEN(scan) += STR_LEN(n);
            next = n + NODE_SZ_STR(n);
            /* Now we can overwrite *n : */
            Move(STRING(n), STRING(scan) + oldl, STR_LEN(n), char);
#ifdef DEBUGGING
            stop = next - 1;
#endif
            n = nnext;
        }
        }

        if (UTF && OP(scan) == EXACTF && STR_LEN(scan) >= 6) {
/*
  Two problematic code points in Unicode casefolding of EXACT nodes:

   U+0390 - GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
   U+03B0 - GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS

   which casefold to

   Unicode            UTF-8

   U+03B9 U+0308 U+0301        0xCE 0xB9 0xCC 0x88 0xCC 0x81
   U+03C5 U+0308 U+0301        0xCF 0x85 0xCC 0x88 0xCC 0x81

   This means that in case-insensitive matching (or "loose matching",
   as Unicode calls it), an EXACTF of length six (the UTF-8 encoded byte
   length of the above casefolded versions) can match a target string
   of length two (the byte length of UTF-8 encoded U+0390 or U+03B0).
   This would rather mess up the minimum length computation.

   What we'll do is to look for the tail four bytes, and then peek
   at the preceding two bytes to see whether we need to decrease
   the minimum length by four (six minus two).

   Thanks to the design of UTF-8, there cannot be false matches:
   A sequence of valid UTF-8 bytes cannot be a subsequence of
   another valid sequence of UTF-8 bytes.

*/
         char *s0 = STRING(scan), *s, *t;
         char *s1 = s0 + STR_LEN(scan) - 1, *s2 = s1 - 4;
         const char * const t0 = "\xcc\x88\xcc\x81";
         const char * const t1 = t0 + 3;

         for (s = s0 + 2;
              s < s2 && (t = ninstr(s, s1, t0, t1));
              s = t + 4) {
              if (((U8)t[-1] == 0xB9 && (U8)t[-2] == 0xCE) ||
              ((U8)t[-1] == 0x85 && (U8)t[-2] == 0xCF))
               min -= 4;
         }
        }

#ifdef DEBUGGING
        /* Allow dumping */
        n = scan + NODE_SZ_STR(scan);
        while (n <= stop) {
        if (PL_regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
            OP(n) = OPTIMIZED;
            NEXT_OFF(n) = 0;
        }
        n++;
        }
#endif
    }
    /* Follow the next-chain of the current node and optimize
       away all the NOTHINGs from it.  */
    if (OP(scan) != CURLYX) {
        const int max = (reg_off_by_arg[OP(scan)]
               ? I32_MAX
               /* I32 may be smaller than U16 on CRAYs! */
               : (I32_MAX < U16_MAX ? I32_MAX : U16_MAX));
        int off = (reg_off_by_arg[OP(scan)] ? ARG(scan) : NEXT_OFF(scan));
        int noff;
        regnode *n = scan;
    
        /* Skip NOTHING and LONGJMP. */
        while ((n = regnext(n))
           && ((PL_regkind[(U8)OP(n)] == NOTHING && (noff = NEXT_OFF(n)))
               || ((OP(n) == LONGJMP) && (noff = ARG(n))))
           && off + noff < max)
        off += noff;
        if (reg_off_by_arg[OP(scan)])
        ARG(scan) = off;
        else
        NEXT_OFF(scan) = off;
    }
    /* The principal pseudo-switch.  Cannot be a switch, since we
       look into several different things.  */
    if (OP(scan) == BRANCH || OP(scan) == BRANCHJ
           || OP(scan) == IFTHEN || OP(scan) == SUSPEND) {
        next = regnext(scan);
        code = OP(scan);
    
        if (OP(next) == code || code == IFTHEN || code == SUSPEND) {
        I32 max1 = 0, min1 = I32_MAX, num = 0;
        struct regnode_charclass_class accum;
        
        if (flags & SCF_DO_SUBSTR) /* XXXX Add !SUSPEND? */
            scan_commit(pRExC_state, data); /* Cannot merge strings after this. */
        if (flags & SCF_DO_STCLASS)
            cl_init_zero(pRExC_state, &accum);
        while (OP(scan) == code) {
            I32 deltanext, minnext, f = 0, fake;
            struct regnode_charclass_class this_class;

            num++;
            data_fake.flags = 0;
            if (data) {        
            data_fake.whilem_c = data->whilem_c;
            data_fake.last_closep = data->last_closep;
            }
            else
            data_fake.last_closep = &fake;
            next = regnext(scan);
            scan = NEXTOPER(scan);
            if (code != BRANCH)
            scan = NEXTOPER(scan);
            if (flags & SCF_DO_STCLASS) {
            cl_init(pRExC_state, &this_class);
            data_fake.start_class = &this_class;
            f = SCF_DO_STCLASS_AND;
            }        
            if (flags & SCF_WHILEM_VISITED_POS)
            f |= SCF_WHILEM_VISITED_POS;
            /* we suppose the run is continuous, last=next...*/
            minnext = study_chunk(pRExC_state, &scan, &deltanext,
                      next, &data_fake, f);
            if (min1 > minnext)
            min1 = minnext;
            if (max1 < minnext + deltanext)
            max1 = minnext + deltanext;
            if (deltanext == I32_MAX)
            is_inf = is_inf_internal = 1;
            scan = next;
            if (data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
            pars++;
            if (data && (data_fake.flags & SF_HAS_EVAL))
            data->flags |= SF_HAS_EVAL;
            if (data)
            data->whilem_c = data_fake.whilem_c;
            if (flags & SCF_DO_STCLASS)
            cl_or(pRExC_state, &accum, &this_class);
            if (code == SUSPEND)
            break;
        }

//... много строк пропущено, чтобы уместить "функцию" в одно сообщение

        case NSPACE:
            if (flags & SCF_DO_STCLASS_AND) {
            if (!(data->start_class->flags & ANYOF_LOCALE)) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_SPACE);
                for (value = 0; value < 256; value++)
                if (isSPACE(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_NSPACE);
            else {
                for (value = 0; value < 256; value++)
                if (!isSPACE(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case NSPACEL:
            if (flags & SCF_DO_STCLASS_AND) {
            if (data->start_class->flags & ANYOF_LOCALE) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_SPACE);
                for (value = 0; value < 256; value++)
                if (!isSPACE(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            data->start_class->flags |= ANYOF_LOCALE;
            ANYOF_CLASS_SET(data->start_class,ANYOF_NSPACE);
            }
            break;
        case DIGIT:
            if (flags & SCF_DO_STCLASS_AND) {
            ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NDIGIT);
            for (value = 0; value < 256; value++)
                if (!isDIGIT(value))
                ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_DIGIT);
            else {
                for (value = 0; value < 256; value++)
                if (isDIGIT(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case NDIGIT:
            if (flags & SCF_DO_STCLASS_AND) {
            ANYOF_CLASS_CLEAR(data->start_class,ANYOF_DIGIT);
            for (value = 0; value < 256; value++)
                if (isDIGIT(value))
                ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_NDIGIT);
            else {
                for (value = 0; value < 256; value++)
                if (!isDIGIT(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        }
        if (flags & SCF_DO_STCLASS_OR)
            cl_and(data->start_class, &and_with);
        flags &= ~SCF_DO_STCLASS;
        }
    }
    else if (PL_regkind[(U8)OP(scan)] == EOL && flags & SCF_DO_SUBSTR) {
        data->flags |= (OP(scan) == MEOL
                ? SF_BEFORE_MEOL
                : SF_BEFORE_SEOL);
    }
    else if (  PL_regkind[(U8)OP(scan)] == BRANCHJ
         /* Lookbehind, or need to calculate parens/evals/stclass: */
           && (scan->flags || data || (flags & SCF_DO_STCLASS))
           && (OP(scan) == IFMATCH || OP(scan) == UNLESSM)) {
        /* Lookahead/lookbehind */
        I32 deltanext, minnext, fake = 0;
        regnode *nscan;
        struct regnode_charclass_class intrnl;
        int f = 0;

        data_fake.flags = 0;
        if (data) {        
        data_fake.whilem_c = data->whilem_c;
        data_fake.last_closep = data->last_closep;
        }
        else
        data_fake.last_closep = &fake;
        if ( flags & SCF_DO_STCLASS && !scan->flags
         && OP(scan) == IFMATCH ) { /* Lookahead */
        cl_init(pRExC_state, &intrnl);
        data_fake.start_class = &intrnl;
        f |= SCF_DO_STCLASS_AND;
        }
        if (flags & SCF_WHILEM_VISITED_POS)
        f |= SCF_WHILEM_VISITED_POS;
        next = regnext(scan);
        nscan = NEXTOPER(NEXTOPER(scan));
        minnext = study_chunk(pRExC_state, &nscan, &deltanext, last, &data_fake, f);
        if (scan->flags) {
        if (deltanext) {
            vFAIL("Variable length lookbehind not implemented");
        }
        else if (minnext > U8_MAX) {
            vFAIL2("Lookbehind longer than %"UVuf" not implemented", (UV)U8_MAX);
        }
        scan->flags = (U8)minnext;
        }
        if (data && data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
        pars++;
        if (data && (data_fake.flags & SF_HAS_EVAL))
        data->flags |= SF_HAS_EVAL;
        if (data)
        data->whilem_c = data_fake.whilem_c;
        if (f & SCF_DO_STCLASS_AND) {
        const int was = (data->start_class->flags & ANYOF_EOS);

        cl_and(data->start_class, &intrnl);
        if (was)
            data->start_class->flags |= ANYOF_EOS;
        }
    }
    else if (OP(scan) == OPEN) {
        pars++;
    }
    else if (OP(scan) == CLOSE) {
        if ((I32)ARG(scan) == is_par) {
        next = regnext(scan);

        if ( next && (OP(next) != WHILEM) && next < last)
            is_par = 0;        /* Disable optimization */
        }
        if (data)
        *(data->last_closep) = ARG(scan);
    }
    else if (OP(scan) == EVAL) {
        if (data)
            data->flags |= SF_HAS_EVAL;
    }
    else if (OP(scan) == LOGICAL && scan->flags == 2) { /* Embedded follows */
        if (flags & SCF_DO_SUBSTR) {
            scan_commit(pRExC_state,data);
            data->longest = &(data->longest_float);
        }
        is_inf = is_inf_internal = 1;
        if (flags & SCF_DO_STCLASS_OR) /* Allow everything */
            cl_anything(pRExC_state, data->start_class);
        flags &= ~SCF_DO_STCLASS;
    }
    /* Else: zero-length, ignore. */
    scan = regnext(scan);
    }

  finish:
    *scanp = scan;
    *deltap = is_inf_internal ? I32_MAX : delta;
    if (flags & SCF_DO_SUBSTR && is_inf)
    data->pos_delta = I32_MAX - data->pos_min;
    if (is_par > U8_MAX)
    is_par = 0;
    if (is_par && pars==1 && data) {
    data->flags |= SF_IN_PAR;
    data->flags &= ~SF_HAS_PAR;
    }
    else if (pars && data) {
    data->flags |= SF_HAS_PAR;
    data->flags &= ~SF_IN_PAR;
    }
    if (flags & SCF_DO_STCLASS_OR)
    cl_and(data->start_class, &and_with);
    return min;
}

А метка в конце — finish user posted image

Автор: Sartorius 8.2.2007, 13:23
SergeCpp, чего-то я перехода на этот финиш тут не вижу  smile 

ЗЫ Упс сорри . Наверно он здесь
Цитата

//... много строк пропущено, чтобы уместить "функцию" в одно сообщение


Но вообще то действительно финиш  smile 

Автор: comnimh 11.2.2007, 18:13
Читаю ветку и сижу удивляюсь, как такая толпа сишников могла забыть про byte order.
Ведь результат работы:
Код
DWORD ver = MAKEWORD(2,3);
и
Код
DWORD ver = 0x0203;
на разных системах может различаться (примем, что на всех целевых системах объявлен тип DWORD и макрос MAKEWORD)!
В винде это будет, как я понимаю (не знаю, как там работает MAKEWORD, сорри) 0x0203 (host order), а вот в той же FreeBSD уже будет 0x03020000 (в случае DWORD, в WORD будет 0x0302) (network order).

И, уже говоря об оптимизации - зачем объявлять эту переменную DWORD и потом присваивать ей вывод MAKEWORD? Два байта лишних smile

Автор: FelikZ 11.2.2007, 18:19
Цитата(comnimh)

Два байта лишних


DWORD = unsigned long;
sizeof(DWORD) = 4!

Автор: comnimh 11.2.2007, 18:22
FelikZ, ну да. Все правильно. Размер DWORD - 4 байта, они пишут в него WORD, размер которого - два байта. Итого два байта лишних.

Автор: bilbobagginz 11.2.2007, 18:27
comnimh, a как вы запишите версию вида: 3.21 ?

Автор: FelikZ 11.2.2007, 18:28
comnimh, звеняй не так понел smile,  но вобще зачем использовать
Код

DWORD ver;


когда можно просто подставить MAKEWORD(2,3) куда надо?

Автор: comnimh 11.2.2007, 18:36
bilbobagginz, 3.21 влезет в WORD, если вы об этом.
Если о byte order - то тогда - тест на это на этапе ./configure и соответствующие телодвижения при компиляции.
А вообще, честно говоря, не понимаю, зачем хранить версию таким образом. Гораздо проще, на мой взгляд, сделать:
Код
#define VERSION_MAJOR 3
#define VERSION_MINOR 21
#define VERSION_POSTFIX "alpha"


Добавлено @ 18:37 
FelikZ, ну мало ли - не факт, что ты будешь один раз в программе использовать эту переменную.

Автор: FiMa1 13.2.2007, 17:46
Цитата(Kuvaldis @ 5.2.2007,  13:30)
ИМХО, по теме есть хорошая книжка
Керниган, Пайк "Практика программирования"

Ребята кто знает где взять? Давно ищу...

Автор: Rockie 13.2.2007, 18:05
Цитата(FiMa1 @  13.2.2007,  17:46 Найти цитируемый пост)
Ребята кто знает где взять? Давно ищу...

искать пробовал?

Добавлено @ 18:07 
http://www.google.md/search?hl=ru&q=%D0%9A%D0%B5%D1%80%D0%BD%D0%B8%D0%B3%D0%B0%D0%BD%2C+%D0%9F%D0%B0%D0%B9%D0%BA+%22%D0%9F%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%BA%D0%B0+%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%22%2C+%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=
http://www.mini-soft.ru/book/tech_prog/index.php

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)