GCC - поясните.

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
Hello, All!

 Hесколько вопросов появилось после юзанья сабж. Возможно глупых. Исходники на
работе, поэтому на пальцах, но если понадобятся притащу.
 1.
 В функции main есть что-то подобное:

union
    {
    uint8_t byte;
    struct
        {
        uint8_t first:1;
        uint8_t second:1;
        };
    }flags;

......
 if (flags.first==1)
    {
    cli();
    flags.first=0;
    sei();
    ..... здесь строчек 5-10 в том числе вызовы функций
    cli();
    flags.second=1;
    sei();
    }
......

 Компилятор при проверке флага first загружает union в регистр а в конце if'а
устанавливает в этом регистре бит и сохраняет в памяти. volatile конечно
спасает, но для меня это несколько неожиданно - соседнии строчки еще туда-сюда,
но чтоб через 5-10...
 2.
 В коротенькой функции использую три раза _delay_ms(). При входе в функцию
компилятор заранее инициализирует значения для делау в шести регистрах. К тому
же несколько регистров обнуляет командой - mov rx,r1 а несколько ldi rx,0.

 Мне не понятно, насколько естественно такое поведение компилятора. Или у меня
какая-то кривая версия загружена? Да, уровень оптимизации - s.

 По-поводу компилятора возникли подозрения из-за того, что сегодня вернулся к
программе которую отложил пару недель назад. Программа перестала делать то, что
выполняла раньше. Разобраться не успел, так как было это под конец работы.
 Hе могу вспомнить когда именно, но недавно скачивал более свежую версию gcc,
так как переставлял винду (ХР). Какую версию лучше установить?

With best regards, Igor.        Time: 18:31        Date: 01 Мар 06

GCC - поясните.
Привет Igor!

01 Mar 06 18:31, Igor Ulanov писал All:

 IU> 1. В функции main есть что-то подобное:

 IU> ......

 IU>  Компилятор при проверке флага first загружает union в регистр а в
 IU> конце if'а устанавливает в этом регистре бит и сохраняет в памяти.

    Вполне логично. Оптимальнее, конечно, вообще flags в память не складывать,
все операции с ней выполнять в регистре, но, видимо, не получилось. Hе бывает
идеальных оптимизаторов.

 IU> volatile конечно спасает,

    От чего спасает? От слишком оптимального кода? :) Результат-то вычислений
все равно одинаковый, а лишнее складывание в память и доставание из памяти -
бессмысленная трата кода.

 IU>  но для меня это несколько неожиданно - соседнии строчки еще
 IU> туда-сюда, но чтоб через 5-10...

    Hадеюсь, это приятная неожиданность. А вопрос-то в чем?

 IU>  2. В коротенькой
 IU> функции использую три раза _delay_ms(). При входе в функцию
 IU> компилятор
 IU> заранее инициализирует значения для делау в шести регистрах. К тому же
 IU> несколько регистров обнуляет командой - mov rx,r1 а несколько ldi
 IU> rx,0.

 IU>  Мне не понятно, насколько естественно такое поведение компилятора.

    Покажи пример кода. Со слов что-либо комментировать трудно. Опять же, не
следует ожидать от оптимизатора абсолютно идеального результата. Если на счету
каждая инструкция, пиши на ассемблере.

 IU> Или у меня какая-то кривая версия загружена?

    В сказанном тобой никакого криминала не вижу.

 IU>  Программа перестала делать то, что выполняла раньше.

    Даю 99.9% за то, что ошибка в программе.

 IU>  Разобраться не успел, так как было это под конец работы. Hе могу
 IU> вспомнить когда именно, но недавно скачивал более свежую версию gcc,
 IU> так как переставлял винду (ХР). Какую версию лучше установить?

    3.4.5 работает без нареканий. Четвертую ветку пока не пробовал.

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Северо-Кавказская межрегиональная ассоциация анонимных соискателей.

GCC - поясните.
Hello, Alex!

(02 Мар 06 00:58), Alex Mogilnikov писАл Igor Ulanov:
 AM>     Покажи пример кода. Со слов что-либо комментировать трудно. Опять
 AM> же, не следует ожидать от оптимизатора абсолютно идеального
 AM> результата. Если на счету каждая инструкция, пиши на ассемблере.

 В том конкретном случае оптимальность не на первом месте.
 Вот С:
uint8_t Read_byte_microlan(void)
{
// функция чтения байта с линиии microlan
uint8_t i,byte;

byte=0;
for (i=0;i<8;i++)
    {
    byte=byte>>1;
    cli();
    microlan_port_down();
    _delay_us(4);
    microlan_port_up();
    _delay_us(13);
    if (PINB & 0x01) byte+=0x80;
    sei();
    _delay_ms(0.06);
    }
return (byte);
}

 Вот результат компиляции:
uint8_t Read_byte_microlan(void)
{
 1fa:   ef 92           push    r14
 1fc:   ff 92           push    r15
 1fe:   0f 93           push    r16
 200:   1f 93           push    r17
 202:   cf 93           push    r28
 204:   df 93           push    r29
 206:   70 e0           ldi r23, 0x00   ; 0
 208:   83 e1           ldi r24, 0x13   ; 19
 20a:   e8 2e           mov r14, r24
 20c:   f1 2c           mov r15, r1
 20e:   01 2d           mov r16, r1
 210:   11 2d           mov r17, r1
 212:   2f e3           ldi r18, 0x3F   ; 63
 214:   30 e0           ldi r19, 0x00   ; 0
 216:   40 e0           ldi r20, 0x00   ; 0
 218:   50 e0           ldi r21, 0x00   ; 0
 21a:   ad ed           ldi r26, 0xDD   ; 221
 21c:   b0 e0           ldi r27, 0x00   ; 0
 21e:   c0 e0           ldi r28, 0x00   ; 0
 220:   d0 e0           ldi r29, 0x00   ; 0
 222:   67 e0           ldi r22, 0x07   ; 7

 22a:   8e 2d           mov r24, r14
 22c:   8a 95           dec r24
 22e:   f1 f7           brne    .-4         ; 0x22c
 230:   b8 98           cbi 0x17, 0 ; 23

 232:   82 2f           mov r24, r18
 234:   8a 95           dec r24
 236:   f1 f7           brne    .-4         ; 0x234
 238:   b0 99           sbic    0x16, 0 ; 22
 23a:   70 58           subi    r23, 0x80   ; 128
 23c:   78 94           sei

 23e:   8a 2f           mov r24, r26
 240:   9b 2f           mov r25, r27
 242:   01 97           sbiw    r24, 0x01   ; 1
 244:   f1 f7           brne    .-4         ; 0x242
 246:   61 50           subi    r22, 0x01   ; 1
 248:   67 ff           sbrs    r22, 7
 24a:   ec cf           rjmp    .-40        ; 0x224
 24c:   87 2f           mov r24, r23
 24e:   99 27           eor r25, r25
 250:   87 fd           sbrc    r24, 7
 252:   90 95           com r25
 254:   df 91           pop r29
 256:   cf 91           pop r28
 258:   1f 91           pop r17
 25a:   0f 91           pop r16
 25c:   ff 90           pop r15
 25e:   ef 90           pop r14
 260:   08 95           ret

 В общем-то конечно терпимо, просто видимо наложилось одно на другое, плюс
конец рабочего дня...

 IU>>  Программа перестала делать то, что выполняла раньше.
 AM>     Даю 99.9% за то, что ошибка в программе.
 Да, так и оказалось. Забыл, что начал изменять программу, когда оторвали от
нее. Вчера SVN поставил, поэтому надеюсь, что от подобных случаев буду
застрахован.
 AM>     3.4.5 работает без нареканий. Четвертую ветку пока не пробовал.
 У меня оказывается еще старее - 3.4.3

 Спасибо за ответ. В общем-то сам во всем виноват, но вчера под конец работы,
когда "рабочая" программа перестала работать поверил бы пожалуй и в барабашек:)

With best regards, Igor.        Time: 18:02        Date: 02 Мар 06

GCC - поясните.
Привет Igor!

02 Mar 06 19:34, Igor Ulanov писал Alex Mogilnikov:

 AM>>     Покажи пример кода. Со слов что-либо комментировать трудно.
 AM>> Опять же, не следует ожидать от оптимизатора абсолютно идеального
 AM>> результата. Если на счету каждая инструкция, пиши на ассемблере.

 IU>  В том конкретном случае оптимальность не на первом месте.
 IU>  Вот С:
 IU> uint8_t Read_byte_microlan(void)
 IU> {
    .......
 IU> }

 IU>  Вот результат компиляции:
 IU> uint8_t Read_byte_microlan(void)
 IU> {
......

    В исходном сишном коде я насчитал семь вызовов функций, а в ассемблерном
коде не вижу ни одного. Ты что, объявил все эти функции инлайновыми? Как-то это
не согласуется с оптимизации по размеру...
    И ассемблерный текст какой-то странный, не похож на то, что обычно генерит
gcc. Вот какой код получился у меня:

Read_byte_microlan:
/* prologue: frame size=0 */
        push r17
        push r28
/* prologue end (size=2) */
        ldi r28,lo8(0)
        ldi r17,lo8(7)
.L6:
        lsr r28
        rcall cli
        rcall microlan_port_down
        ldi r24,lo8(4)
        ldi r25,hi8(4)
        rcall _delay_us
        rcall microlan_port_up
        ldi r24,lo8(13)
        ldi r25,hi8(13)
        rcall _delay_us
        lds r24,PINB
        sbrc r24,0
        subi r28,lo8(-(-128))
.L5:
        rcall sei
        ldi r22,lo8(0x3d75c28f)
        ldi r23,hi8(0x3d75c28f)
        ldi r24,hlo8(0x3d75c28f)
        ldi r25,hhi8(0x3d75c28f)
        rcall _delay_ms
        subi r17,lo8(-(-1))
        sbrs r17,7
        rjmp .L6
        mov r24,r28
        clr r25
/* epilogue: frame size=0 */
        pop r28
        pop r17
        ret
/* epilogue end (size=3) */

 IU> При входе в функцию компилятор заранее инициализирует значения для
 IU> делау в шести регистрах. К тому же несколько регистров обнуляет
 IU> командой - mov rx,r1 а несколько ldi rx,0.

    По-поводу этих двух команд: они дают одинаковый результат, т.к. avr-gcc
обычно в r1 держит 0, и в коде так его и называет - __zero_reg__. Кстати, у
меня он им ни разу не воспользовался. Откуда берется ldi rx,0 из моего варианта
кода понятно - это загрузка старшего байта константы.

 IU>  В общем-то конечно терпимо, просто видимо наложилось одно на
 IU> другое, плюс конец рабочего дня...

 IU>>>  Программа перестала делать то, что выполняла раньше.
 AM>>     Даю 99.9% за то, что ошибка в программе.
 IU>  Да, так и оказалось. Забыл, что начал изменять программу, когда
 IU> оторвали от нее. Вчера SVN поставил, поэтому надеюсь, что от подобных
 IU> случаев буду застрахован.

    Сделал ты все правильно, но застрахован не будешь. :) Во-первых, свои
ошибки вообще трудно заметить. Во-вторых, ошибка может быть весьма хитрой.
В-третьих, она может оказаться вообще не в твоем коде, а в какой-нибудь
библиотеке. Вот, кажется, при переходе с gcc-3.1 на gcc-3.3 я получил мертвое
зависание при старте давно отлаженной программы. Оказалось, проблема была в
библиотечном ctrend.c, имеющем такое содержание:

======== crtend.c ========
typedef void (*fptr)(void);

static fptr ctor_end[1] __attribute__((section(".ctors"), __unused__)) = { 0 };
static fptr dtor_end[1] __attribute__((section(".dtors"), __unused__)) = { 0 };
==========================

    Поскольку ctor_end и dtor_end нигде не использовались, оптимизатор gcc-3.2
их просто выкинул (gcc-3.1 оставлял), в результате таблица конструкторов
глобальных объектов оказалась без завершающего нуля, и стартап вис при попытке
выполнить мусор.

 AM>>     3.4.5 работает без нареканий. Четвертую ветку пока не пробовал.
 IU>  У меня оказывается еще старее - 3.4.3

    Фигня, некоторые до сих пор 2.96 используют. А вот четвертую ветку
любопытно попробовать, но, наверное, для ARM, т.к. avr я уже практически не
использую...

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Владею дыроколом на уровне пользователя.

Re: GCC - поясните.
Hello, Kirill!
You wrote to Igor Ulanov on Fri, 03 Mar 2006 10:39:36 +0500:

 KF> Суть в том, что проще, для программиста, иметь одну
 KF> переменную однозначно определяющую состояние своим числовым
 KF> значением (1, 2... N), чем десяток переменных вместо того.
 KF> И, соответственно, определять реакцию на различные события для
 KF> каждого из N состояний по-отдельности. Удобно, что в любой момент
 KF> времени известно, в каком состоянии находится система и известны
 KF> все её реакции на все возможные события. Работа системы легко
 KF> протоколируется. Возможно аналитически проверить правильность
 KF> системы в целом.С флагами это всё конечно тоже так, но учесть все
 KF> флаги с их 2^n числом состояний, что типично много больше N --
 KF> сложно.
Hе понял.
Почему   N != 2^n ?

With best regards, Andrej Arnold.  E-mail: snipped-for-privacy@aol.com



Re: GCC - поясните.

Quoted text here. Click to load it

  Потому что состояний может быть меньше, чем 2^n флагов. Например,
какой-то флаг в каком-то состоянии не имеет смысла. А наоборот быть не
может.


GCC - поясните.
Привет, Alex !


 03 Mar 06 , 00:42  Alex Mogilnikov писал к Igor Ulanov:

IU>>  У меня оказывается еще старее - 3.4.3

AM>     Фигня, некоторые до сих пор 2.96 используют. А вот четвертую ветку
AM> любопытно попробовать, но, наверное, для ARM, т.к. avr я уже
AM> практически не использую...

2.9_6_ - это вроде бы какой-то гнусный хак/патч от редхата, не совместимый ни с
чем.

.                                            С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... Выползень роду женского подло нарушил  Обряд Чистописания

GCC - поясните.
Привет Nickita!

03 Mar 06 20:59, Nickita A Startcev писал Alex Mogilnikov:

 NS> 2.9_6_ - это вроде бы какой-то гнусный хак/патч от редхата, не
 NS> совместимый ни с чем.

    Возможно. Hе помню точно, чем там вторая ветка кончилась. 2.95 наверное?

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Собака - вдруг человека...

Re: GCC - поясните.

Quoted text here. Click to load it

  Ага. В дебиане именно он, без всяких редхатов.


GCC - поясните.
Привет, Alex !


 04 Mar 06 , 15:18  Alex Mogilnikov писал к Nickita A Startcev:

NS>> 2.9_6_ - это вроде бы какой-то гнусный хак/патч от редхата, не
NS>> совместимый ни с чем.

AM>     Возможно. Hе помню точно, чем там вторая ветка кончилась. 2.95
AM> наверное?

Именно.

.                                            С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... Пристают к [За/Под]ставе гости

GCC - поясните.
Hello, Alex!

(03 Мар 06 00:42), Alex Mogilnikov писАл Igor Ulanov:
 AM>     В исходном сишном коде я насчитал семь вызовов функций, а в
 AM> ассемблерном коде не вижу ни одного. Ты что, объявил все эти функции
 AM> инлайновыми? Как-то это не согласуется с оптимизации по размеру...
 Они объявлены так в библиотеке. Я ничего не менял.
 AM>     И ассемблерный текст какой-то странный, не похож на то, что обычно
 AM> генерит gcc.
 Я смотрю текст в файле для отладчика с расширением lss, мне так удобнее, так
как там присутствует и Сишный текст.
 У тебя библиотека явно отличается от моей. Приду на работу скачаю все-таки что
нибудь поновей. А пока изменил delay.h:

static __inline__ void _delay_loop_1(uint8_t __count)
{
    __asm__ volatile (
        "1: dec %0" "\n\t"
        "brne 1b"
        : "=r" (__count)
        : "0" (__count)
    );
}

static __inline__ void _delay_loop_2(uint16_t __count)
{
__asm__ volatile (
    "1: sbiw %0,1" "\n\t"
    "brne 1b"
    : "=w" (__count)
    : "0" (__count)
    );
}

static __inline__ void _delay_loop_3(uint16_t __count_w, uint8_t __count)
{

__asm__ volatile (
    "1:"            "\n\t"
    "2:"            "\n\t"
    "sbiw   %0,1"   "\n\t"
    "brne   2b"     "\n\t"
    "dec    %1"     "\n\t"
    "brne   1b"     "\n\t"
    :: "w" (__count_w), "r" (__count)
    );
}

static __inline__ void _delay_us(double __us)
{
double __tmp=(F_CPU/3e6)*__us;

if (__tmp<1.0) _delay_loop_1(1);
    else if (__tmp<256) _delay_loop_1((uint8_t)__tmp);
        else if (__tmp<65536) _delay_loop_2((uint16_t)(F_CPU/4e6)*__us);
            else _delay_loop_2(0);
}

static __inline__ void _delay_ms(double __ms)
{
double __tmp =(F_CPU/3e3)*__ms;

if (__tmp<1.0) _delay_loop_1(1);
    else if (__tmp<256) _delay_loop_1((uint8_t)__tmp);
        else
            {
            __tmp=(F_CPU/4e3)*__ms;
            if (__tmp<65536) _delay_loop_2((uint16_t)__tmp);
            else if (__tmp<16777216)
_delay_loop_3((uint16_t)(__tmp-(__tmp/65536)),(uint8_t)(__tmp/65536));
                else _delay_loop_3(0,0);
            }
}

Теперь хоть нет идиотского ограничения в _delay_us(), с которым я имел проблему
пока не посмотрел что делает функция в исходнике.

 AM>     Сделал ты все правильно, но застрахован не будешь. :)
 Hо надеюсь SVN избавит от лихорадочных попыток вспомнить, какие изменения
вносились когда решал ту или иную задачу. Сейчас пожалуй это основная проблема.
 AM>  Во-первых, свои ошибки вообще трудно заметить.
 Да, к великому сожалению это так. Практически совершено не заметны "опечатки",
так как когда смотришь исходник в большей степени "читаешь" не его, а свои
воспоминания о решениях. Если бы можно было бы выключать отдельные участки
памяти было бы намного проще:)

По-поводу SVN. В русском описании есть предупреждение, что хранилище нельзя
располагать на "сетевой шаре" - это так? Мне очень удобно было бы расположить
свое хранилище на сервере. Или под "сетевой шарой" понимается что-то другое?

With best regards, Igor.        Time: 14:22        Date: 04 Мар 06

Re: GCC - поясните.

Quoted text here. Click to load it

  delay() вообще имеет смысл или только для очень коротких временных
интервалов, или в случае, когда вся программа посчитана по тактам, чего
на C сделать невозможно.


GCC - поясните.
Привет Igor!

04 Mar 06 14:22, Igor Ulanov писал Alex Mogilnikov:

 AM>>     И ассемблерный текст какой-то странный, не похож на то, что
 AM>> обычно генерит gcc.
 IU>  Я смотрю текст в файле для отладчика с расширением lss, мне так
 IU> удобнее, так как там присутствует и Сишный текст.

    Тогда тебе еще удобней будет смотреть ассемблерный листинг. В нем, по
крайней мере, ассемблерный текст в неизменном виде. А в твоем lss, похоже,
текст получен дизассемблированием из машинных кодов. Hу не пишет gcc "brne
.-4", он для переходов метки ставит. :)

 IU>  У тебя библиотека явно отличается от моей.

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

========== test.c ===========
#include <inttypes.h>   /* только ради uint8_t */

void cli(void);
void sei(void);
void microlan_port_down(void);
void microlan_port_up(void);
void _delay_us(unsigned int);
void _delay_ms(float);

extern uint8_t PINB;

uint8_t Read_byte_microlan(void)
{
// функция чтения байта с линиии microlan
    uint8_t i, byte;

    byte = 0;
    for(i = 0; i < 8; i++)
    {
        byte = byte >> 1;
        cli();
        microlan_port_down();
        _delay_us(4);
        microlan_port_up();
        _delay_us(13);
        if(PINB & 0x01)
            byte += 0x80;
        sei();
        _delay_ms(0.06);
    }
    return (byte);
}
=============================

 IU> По-поводу SVN. В русском описании есть предупреждение, что хранилище
 IU> нельзя располагать на "сетевой шаре" - это так?

    Hе знаю, я использую CVS, и его репозиторий только через сеть и доступен.
Тут многие svn используют, я думаю, подскажут тебе.

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Посетители должны общаться по сети.

Re: GCC - поясните.

   Kirill, ты ещё здесь сидишь?


Воскресенье Март 05 2006 13:04, Kirill Frolov wrote to Ruslan Mohniuc:

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

 Тебе кто-то мешает _игнорировать_ конкретный флаг в том состоянии, когда
он не имеет значения?
 Тем более, что в приведенном тобой случае флаг "режима открытия" разумно
предусматривать не для каждого имеющегося файла, а только для списка открытых
файлов! Память сэкономишь...


                                                   Георгий


Re: GCC - поясните.

Quoted text here. Click to load it


  Сам себе мешаю.


Re: GCC - поясните.

   Kirill, ты ещё здесь сидишь?


Понедельник Март 06 2006 11:29, Kirill Frolov wrote to George Shepelev:

 >> KF>   Потому что состояний может быть меньше, чем 2^n флагов.
 >> KF> Hапример, какой-то флаг в каком-то состоянии не имеет смысла. А
 >> KF> наоборот быть не может.
 >>  Это правильно, но будет ли удобно с ними работать? Простенький
 >> пример, анализ состояния дверей автомобиля. Вместо простенького
 >> описания вида "это флажок закрытия передней левой двери, а это
 >> флажок закрытия передней правой..." будет страшненький список
 >> состояний вида "левая передняя дверь открыта, причём правая передняя
 >> закрыта, левая задняя тоже закрыта, и правая задняя тоже закрыта..."
 KF>   Я ж писал: можно разбить на несколько автоматов.

 Дополнительно усложняя анализ! И ради чего, наверное ради мифической
"идеологической правильности"?

 KF> Потому как хоть и можно всё описывать исключительно одним состоянием,
 KF> это ненаглядно и число их (они перемножаются) очень велико. В данном
 KF> случае целесообразно для каждой двери иметь своё состояние.

 А это и значит - использовать флаги! ;)))

 KF> Hо где-то наоборот.

 Верю. Hо неоправданно обобщать-то те случаи, которые "наоборот",
не надо, да?


 >> в которой при одних условиях размещается таймер режимов
 >> стеклоочистителя, а в других - код с "охранки". Экономия в один
 >> жалкий байт и куча возможностей для нелепых ошибок в программе...
 KF>   А в описанном случае с файлом лучше иметь состояния. Потому как
 KF> очень легко наступить на грабли при попытке поработать с закрытым
 KF> файлом.

 Глупости.

 Кстати, некоторые программы (к примеру вьюер FAR'а) помнят, в каком
режиме открывался файл в прошлый раз (т.е. помнят его, когда файл
закрыт) и при очередном открытии восстанавливают именно этот режим.
Удобно.


                                                   Георгий


Re: GCC - поясните.


Quoted text here. Click to load it

  Нет. Практически проще и менее багоопасно.

Quoted text here. Click to load it

  Нет, не значит. Состояний может быть более двух. А флаги -- это
искусственное дробление системы на множество автоматов с двумя
состояниями каждый. При этом как оно между собой будет взаимодействовать
-- всё весмь в неявном виде.

Quoted text here. Click to load it

  Есть глупости, а есть просто шаблоны программирования. Вроде того, что
не нужно хранить одну величину в 10 переменных или одно состояние в
десятке флагов.

Quoted text here. Click to load it

  Я имею ввиду fopen, fclose().


Re: GCC - поясните.
Hi Kirill !

 Совсем недавно 04 Mar 06 15:36, Kirill Frolov писал к  Andrej Arnold:

 >> Hе понял.
 >> Почему   N != 2^n ?

 KF>   Потому что состояний может быть меньше, чем 2^n флагов. Hапример,
 KF> какой-то флаг в каком-то состоянии не имеет смысла. А наоборот быть не
 KF> может.
"Hе может быть" и "Hе имеет смысла" - это две большие разницы. Если твоя
эхотажная программа не знает что делать в ситуациях, которые "не имеют смысла"
- это ненадежное программирование.


         WBRgrds
                   Ruslan


Re: GCC - поясните.

Quoted text here. Click to load it

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

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


Re: GCC - поясните.

   Kirill, ты ещё здесь сидишь?


Суббота Март 04 2006 15:36, Kirill Frolov wrote to Andrej Arnold:

 >> KF> системы в целом.С флагами это всё конечно тоже так, но учесть
 >> KF> все флаги с их 2^n числом состояний, что типично много больше N
 >> KF> -- сложно.
 >> Hе понял.
 >> Почему   N != 2^n ?
 KF>   Потому что состояний может быть меньше, чем 2^n флагов. Hапример,
 KF> какой-то флаг в каком-то состоянии не имеет смысла. А наоборот быть не
 KF> может.

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


                                                   Георгий


Site Timeline