ICC AVR и стpоки

22-Sep-03 03:08 Harry Zhurov wrote to Oleksandr Redchuk:

HZ> Что-то тут накладка, по ходу, вышла? Отвечаешь, вроде, BP, а X-CT ко HZ> мне HZ> (оно у меня ярко-зеленым цветом выделяется на фоне остальных сообщений). HZ> :) Никакой накладки. Я тебе и писал, дополнения к его письму.

OR>> Реально if (KbdHit()) при KbdHit() - не inline функции выливается в OR>> rcall / tst / breq, а инлайновая Kbd.IsHit() хорошо если оптимизируется OR>> до lds Kbd.flag / tst / breq (уже не короче), а то ведь и OR>> ldi zh/zl, Kbd / ldd Z+offset field / tst / breq может выйти (ну OR>> нет у меня IAR EC++, а работа gcc с этим делом тут уже отмечалась :-()

HZ> В общем случае: HZ> C : rcall / lds / tst / ... / ret / tst HZ> C++ : ldi / ldi / ldd / tst HZ> В частном случае: HZ> C : rcall / lds / ret / tst HZ> C++ : lds / tst Я имел ввиду размер в точке вызова (суммарный объём кода), а не время выполнения проверки. Меня обычно не волнует время проверки "а есть ли байт в буфере уарт?", "а закончился ли цикл оцифровки по всем

6 каналам?" и т.п.

HZ> { HZ> if(slon.IsTrue()) y = 1; HZ> } HZ> // -------------------------------------

HZ> main: HZ> 9100.... LDS R16,(slon + 2) HZ> 2300 TST R16 HZ> F031 BREQ ??main_0 В C-шном варианте это выглядело бы как rcall SlonIsTrue tst r16 breq либо call для мега16 и выше. Т.е. inline не короче. А если там проверка битового флага в поле, то инлайновый вариант ещё толще будет.

HZ> далеко не идеал. В этом же основная причина появления оверхеда при HZ> переходе с асма на С. Ну да. Именно это я и пытаюсь тебе сказать. И именно поэтому есть куча задач, где C++ нафиг не нужен, так же как и ещё остались задачи, для которых нафиг не нужен C, можно легко и быстро сделать на асме. Но вот уже довольно много задач, решаемых на асме "грустновато" и много людей, уверенно перешедших на C. И в этом случае им проще и те мелкие задачки тоже на C написать. Вот когда они (мы) будем большинство задач делать на C++, тогда и 4-канальный АЦП на RS232 будет весь из себя на классах писаться, чтобы "руку не сбивать". Ну нет у меня таких задач, где C++ "аж пыщыть" как _нужен_. А ты пытаешься доказать, что его _можно_и_нужно_ применять и для простых задач. А я говорю, что его можно применять _И_ для простых задач, если без него всё равно не жить, а так -- нет смысла, разве что из любопытства или идейных соображений.

wbr,

Reply to
Oleksandr Redchuk
Loading thread data ...

Hello "Harry.

22 Sep 03 20:44, you wrote to me:

HZ>>> вполне работоспособен, хотя это и грязный хак, имхо. С не-POD HZ>>> типом такое не пройдет. AB>> Почему? HZ> Что почему? Почему грязный хак?

Вообще-то я спрашивал почему не пройдет.

HZ> Да потому, что действует в обход HZ> системы типов и компилятор тут не может проверить соответствует ли HZ> адресуемая память типу объекта, к которому приводится.

В приведенном тобой примере - пройдет.

HZ> И в случае HZ> неправильного приведения получишь безобразный баг во всей красе.

Hо ты сделал правильное приведение, не так ли?

Alexey

Reply to
Alexey Boyko

Hello "Harry.

22 Sep 03 20:44, you wrote to me:

AB>> Поробуй сделать без указателей: на 4-х массивах - current, min, AB>> max, delta AB>> И сравни.

HZ> Пробовал и сравнивал. Получается по сгенеренному коду примерно то HZ> же самое, только в этом случае приходится руками создавать массивы, HZ> руками их инициализировать, руками организовывать в _каждой_ HZ> вызываемой функции обращение к _своей_ переменной 'Value',

По индексу в массиве. Одномерные массивы не есть чем-то очень сложным и тяжелым для понимания.

HZ> словом, все HZ> то, что делает компилятор (и делает без ошибок), придется делать HZ> руками.

А так руками нужно описывать разные классы. Если в программу с массивами нужно добавить еще одно значение, нужно просто удлиннить массивы, а на С++ - создать новый класс. Сколько еще строк понадобится?

HZ> Исходный код в этом случае выглядит, поверь мне, не HZ> симпатично, мягко говоря.

void Increment(int index) { current[index] += delta[index]; if (current[index] > max[index]) current[index] = max[index]; }

Анналогично декремент, вывод на экран, конечно, немного сложнее.

HZ> А если учесть, что сами vtbl компилятор HZ> помещает во флеш, то для достижения того же самого исходный код на HZ> С придется "украсить" пачкой __flash.

Вообще-то меня С++ не устраивает, потому-что с ним получается многовато указателей на функции, с которыми АВРу не очень удобно работать.

Обычно, без них можно обойтись. switch на 5-6 значений будет еффективнее и по коду и по количеству строк.

Хотя, конечно, есть такие задачи, в которых С++ будет удобнее, и тогда уже наплевать на оверхеды всякие. Мне, в принципе, такие уже попадались, только духу не хватает перепроектировать программу. (Работает - и пусть работает)

Alexey

Reply to
Alexey Boyko

Hello "Harry.

22 Sep 03 20:44, you wrote to me:

AB>> Если ты не в курсе, то кодогенертор в gcc не знает ни про Си, ни AB>> про Си++. Он преобразует из некоторого абстрактного языка в AB>> ассемблер. Так что если написан кодогенератор для msp-430, то Си++ AB>> появляется как бы автоматически. Hужно только в библиотеке AB>> некоторую поддержку дописать. HZ> А в чем состоит поддержка в библиотеке?

Я точно не знаю, что-то про конструкторы. Hужно изучить, что в avr-libc сделали для этого.

OR>>>> можно сделать static struct { ... } uarts[USED_UARTS]; и всю OR>>>> работу делать по индексам. HZ>>> А что, их (UART'ов) много что-ли? А если один? HZ>>> И потом, это смахивает на проделывание вручную того, что HZ>>> делает ++ный компилятор. AB>> ++ный компилятор автоматически определит количество и тип уартов в AB>> контроллере и объявит массив объектов? HZ> Я имел в виду не это, а то, что нужно руками индексы метать...

В библиотечных функциях - да, надо. Hо зато один раз. К тому же я перепробовал несколько вариантов на Си, выбирая, который компилятору понятнее и может сделать код еффективнее. Сейчас библиотека УАРТа не самая читабельная, но я ее просто копирую из проекта в проект и не смотрю в нее.

Hа классах есть только один способ и оптимизировать там нечего. Только на компилятор приходится надеятся.

AB>> А в Си inline отменили? HZ> А в Си inline не было от рождения! Только сейчас в С99 его, вроде HZ> бы, включили. То, что это есть в любимом GCC,

Повезло мне. А что в ИАР С нету inline?

HZ> Кстати, как в gcc размещать данные во флеши?

Вообще gcc не поддерживает разные классы памяти, поэтому с размещением данных во флеше есть проблемы.

HZ> А как на gcc это сделать?

Есть макрос: #define PROGMEM __attribute__ ((__progmem__))

А переменные объявляются как:

char buf[16] PROGMEM;

Для доступа к таки переменным есть макрос PRG_RDB Hапример - PRG_RDB(&buf[4])

HZ> И еще до кучи: можно ли каким-то образом указать функции, чтобы в HZ> ней не сохранялись используемые регистры, типа того, что в ИАРе HZ> достигается с помощью __task.

Да. Что-то вроде: void task1() __attribute__ ((noreturn)); void task1() { run(); }

Есть еще интересные аттрибуты, например: pure - результат функции зависит только от входных параметров, и не влияет на глобальные переменные. Если в выражении такая функция вызывается несколько раз с одинаковыми аргументами, то компилятор вызовет ее только один раз.

format - означает, что в функцию передается строка формата, такая же, как в printf и компилятор может на этапе компиляции проверить соответствие передаваемых аргументов строке формата.

section - поместить функцию или переменную в нужный сегмент (секцию). Так поступают в avr-gcc с EEPROM (__progmem__ делает почти тоже самое)

deprecated - при использовании функции будет выдан варнинг, что она - deprecated

weak - если при линковке будет обнаружена еще одна функцияс таким же именем, то предпочтение будет отдано той, которая без аттрибута weak.

interrupt - и так понятно.

signal - почти то же, что и interrupt

naked - не имеет пролога и эпилога. Возможно - это подойдет лучше, чем noreturn

AB>> А вот шаблоны видимо действительно хорошая вещь. Я правда не знаю, AB>> как ими пользоваться, но судя по примерам - это то что нужно. HZ> Шаблоны - параметризованный тип. Это позволяет не писать HZ> одинаковый код для разных типов, а написать один раз шаблон, а потом HZ> инстанцировать переменные по шаблону с нужным типом. Hапример, имеем HZ> кольцевой буфер (FIFO), который работает с байтами. А еще нужно такой HZ> же буфер для интов, даблов, структур и проч. Тогда создаем шаблон:

Это я уже знаю. Такие примеры видел в STL. Я имел ввиду, что не знаю, как ими пользоваться. Hадо будет, наверное, какую нибудь книжку по С++ купить.

HZ> Собран он. Есть у меня. Только после ИАРа на него что-то ломает HZ> переползать. :)

Alexey

Reply to
Alexey Boyko

Hello Oleksandr.

23 Sep 03 11:22, you wrote to "Harry Zhurov":

HZ>> main: HZ>> 9100.... LDS R16,(slon + 2) HZ>> 2300 TST R16 HZ>> F031 BREQ ??main_0 OR> В C-шном варианте это выглядело бы как OR> rcall SlonIsTrue OR> tst r16 OR> breq OR> либо call для мега16 и выше. Т.е. inline не короче. OR> А если там проверка битового флага в поле, то инлайновый вариант OR> ещё толще будет.

А если подумать?

Если это просто проверка байта, то уже есть смысл перейти на инлайн, так как он хоть и столько же занимает, но работает быстрее.

А во вторых, ты не учел тот факт, что вызов функции сразу же делает невалидными половину регистров, в которых могло быть что-то полезное и потребует повторную загрузку.

Можно, конечно, попробовать сделать функцию просто static, и проверить будет ли компилятор смотреть, какие регистры портит вызываемая функция.

Alexey

Reply to
Alexey Boyko

В статье snipped-for-privacy@p4.f.n4624.z2.ftn> Alexey Boyko написал(а):

11930 байт - это исходников, в основном инлайнов и макро. Что из этого получается я не мерял - это мелочи по сравнению с основным кодом.
Reply to
Dmitry Fedorov

BP>> ИАР с cross_call: 13754 BP>> ИАР без cross_call: 15322 BP>> avr-gcc: 22140 OR> Что-то много. Ключики покажи.

-O2 -Wa,-ahlms=gcc161/main.lst

-g -mmcu=atmega161 -W -Wall -Wstrict-prototypes -funsigned-char

-funsigned-bitfields -fpack-struct -fshort-enums -finline-functions OR> Пока единственное, что я заметил резкое - это при применении OR> float сразу gcc-шный растёт за счёт библиотеки (т.е. по мапе OR> видно, что мой код пояти не отличается по размеру, а прилинковано

Нет, у меня нет никаких float и стандартная библиотека почти не используется.

Прогнал самый большой файл с разными опциями -O и вот что вышло:

ИАР GCCfl GCC(1) GCC(2) 4538 -O0 6554 -O1 6554 -O2 6486 5960 -O3 6500 -Os 5186 5888

GCC(1) параметры указанные выше, GCC(2) без -finline-functions. Весь проект собранный GCC(1)/-Os - 17638, GCC(2)/-Os - 19442.

Действительно, при оптимизации по размеру (ИАР оптимизировал по скорости), соотношение намного лучше - 1.15. На досуге попробую посмотреть, что еще можно поправить в коде или подкрутить в опциях.

Reply to
Boris Popov

Oleksandr Redchuk wrote to "Harry Zhurov" snipped-for-privacy@online.nsk.su> on Mon, 22 Sep 2003 18:26:59 +0000 (UTC):

[...]

HZ>> Вопрос-то был: "Почему в С++ нет модулей?". OR> если в большинстве случаев достаточно их.

Но зачем при наличии классов вводить еще и модули? Если достаточно модульной функциональности, то и использовать класс не во всю мощь, а ограниченно - как пространство имен. Или даже просто пространства имен и юзать.

HZ>> конкретное действие. Только на С будет оверхед на вызов, а в плюсах эту HZ>> функцию HZ>> просто делаешь инлайновой. Т.е. эффективность как при прямом обращении, OR> А вот это (эффективность инлайновых функций) очень зависит OR> от того, на каком процессоре и какое действие производится. OR> Ну по скорости вопросов нет, inline быстрее, а вот по объёму OR> ещё вопрос. Даже на if( flag) при флаге равном "единице обработки" OR> (байт/слово). А если flag - битовое поле или if (flag & 0x20),

А какая разница флаг или нет. Загружается переменная из ОЗУ и дальше логическая операция. Загрузка в любом случае одинакова, а разница в подходах только в ней.

OR> то inline по объёму проиграет (если процессор не имеет команды проверки OR> бита прямо в памяти). И не inline метод не имеет никакого преимущества.

Не понял. Пример кода можно привести, где это проявится?

HZ>> Тут разница половая: public в классе делаются функции, а не данные. HZ>> А на С HZ>> придется данные открывать. А если через функцию, то оверхед на вызов, HZ>> который при простом чтении переменной оказывается чересчур большим. OR> Примерчик кода приведи. А то у меня EC++ нет. OR> а gcc для inline объём явно больше.

Что, и для однократного применения?

OR> Кстати, gcc ещё иногда любит в полном соответствии со стандартом расширять OR> char до int при вычислениях. Тоже неблагоприятно на коде сказывается.

ИАР это тоже делает, но оптимизатор после убирает лишнее. Был даже случай в версии 2.25B, когда выражение

byte1 = byte2 << 4;

приводило к тому, что byte2 расширялось до инта, и затем оба байта двигались на 4 бита. На это было указано. Они сказали, что так положено в соответствии со стандартом, и это не баг. Но приняли к сведению, что оптимизатор не на высоте. В 2.25С это пофиксили и оно стало компилироваться в положенные

swap r16 andi r16,0xf0

OR> class foo { OR> uchar ch;

[...]

Изволь.

Файл "slon.h"

======================================== typedef unsigned char uchar;

class foo { uchar ch; public: foo(uchar _ch) { ch=_ch; } bool IsChar0() { return ch==0; } bool IsChar0Proc(); bool IsBit3() { return bool(ch & (1<<3)); } bool IsBit3proc(); };

uchar IsChar0(); uchar IsBit3(); bool fooIsBit3proc(); ========================================

Файл "slon1.cpp"

======================================== #include "slon.h"

static uchar ch=5;

uchar IsChar0() { return ch==0; } uchar IsBit3() { return ch & (1<<3); } bool fooIsBit3proc() { return bool(ch & (1<<3)); } ========================================

Файл "slon.cpp"

======================================== #include "slon.h"

bool foo::IsChar0Proc() { return ch==0; }

foo ff(5);

uchar moo1() { uchar cc=0;

if( ff.IsChar0() ) ++cc; if( ff.IsBit3() ) ++cc; return cc; }

uchar moo() { uchar cc=0;

if( IsChar0() ) ++cc; if( IsBit3() ) ++cc; return cc; } ========================================

Результаты компиляции.

С++ вариант.

---------------------------------------- uchar cc=0;

if( ff.IsChar0() ) ++cc;

9100.... LDS R16,ff 2300 TST R16 F411 BRNE ??moo1_1 E001 LDI R16,1 C001 RJMP ??moo1_2 ??moo1_1: E000 LDI R16,0 if( ff.IsBit3() ) ++cc; ??moo1_2: .... LDI R30,LOW(ff) .... LDI R31,(ff) >> 8 8110 LD R17,Z FD13 SBRC R17,3 9503 INC R16 return cc; 9508 RET

----------------------------------------

На мой взгляд лучше бы он вместо первого lds'а сразу бы загрузил указатель, как во втором случае. Т.ч. тут парням еще есть над чем работать.

С вариант.

----------------------------------------

938A ST -Y,R24 uchar cc=0;

if( IsChar0() ) ++cc; .... RCALL ??IsChar0

2300 TST R16 F011 BREQ ??moo_1 E081 LDI R24,1 C001 RJMP ??moo_2 ??moo_1: E080 LDI R24,0 if( IsBit3() ) ++cc; ??moo_2: .... RCALL ??IsBit3 2300 TST R16 F009 BREQ ??moo_3 9583 INC R24 return cc; ??moo_3: 2F08 MOV R16,R24 9189 LD R24,Y+ 9508 RET

----------------------------------------

И еще плюс сами функции:

---------------------------------------- uchar IsChar0() { return ch==0; } ??IsChar0: 9100.... LDS R16,ch 2300 TST R16 F411 BRNE ??IsChar0_1 E001 LDI R16,1 9508 RET ??IsChar0_1: E000 LDI R16,0 9508 RET

uchar IsBit3() { return ch & (1<<3); } ??IsBit3: 9100.... LDS R16,ch 7008 ANDI R16,0x08 9508 RET

----------------------------------------

Суди сам.

Все же оптимизатор у ИАРа неплох! Тут было заявление, что скоро gcc догонит IAR. Очень сомневаюсь, что это произойдет скоро, и даже сомневаюсь, что это вообще произойдет - ИАР тоже на месте не стоит.

...so long!

### Земля вращается вокруг своей оси - это позволяет нам измерять время суток.

Reply to
Harry Zhurov

Oleksandr Redchuk wrote to "Harry Zhurov" snipped-for-privacy@online.nsk.su> on Mon, 22 Sep 2003 18:26:59 +0000 (UTC):

HZ>> void uartInit(BYTE* Rx_buf, HZ>> BYTE Rx_size, HZ>> BYTE* Tx_buf, HZ>> BYTE Tx_size, HZ>> BYTE Baud_rate); OR> Я не понял - почему тут куча параметров, а у конструктора OR> ниже только baud rate? Значит, это _разные_ по поведению OR> системы, если там конструктор распределяет себе буфера по своему OR> усмотрению.

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

HZ>> void uartDisable_Rx(void); OR> [...] HZ>> BOOL uartWrite_Tx_data(BYTE* ptr, BYTE count); OR> Этих функций нет в открытой части класса ниже, значит OR> они могут быть static в файле uart.c и не блестеть тут.

HZ>> interrupt void UART_Rx_interrupt(void); HZ>> interrupt void UART_UDRE_interrupt(void); OR> Аналогично, если у тебя класс ниже работает через прерывания, то OR> эти функции есть. Блестеть наружу им нечего, спрятаны и так, OR> и так где-то в uart.c или uart.cpp

HZ>> BYTE UART_block_buf[BLOCK_BUFFER_SIZE]; OR> Опять - в "классовой" версии буфер из воздуха взялся? OR> Всё равно где-то кто-то его распределяет.

HZ>> void (*fptrCmd[])(void) = HZ>> { HZ>> read_SRAM, HZ>> write_SRAM, HZ>> log_op, HZ>> read_FLASH, HZ>> read_EEPROM, HZ>> write_EEPROM, HZ>> uart_cmd_user HZ>> }; OR> И реакцию на команды у класса так или иначе надо прописать.

Все это, конечно, есть (я и не говорил, что нет - наоборот, говорил, что определение класса столь же обширно, просто не стал загромождать письмо; у тебя кстати, afair, имеются обсуждаемые сорцы). Но... (см ответ на следующую цитату)

HZ>> Вот это все "живет" в глобальном пространстве имен. Там еще пара OR> ПОЧЕМУ? OR> Почему бОльшая часть этого не может быть static внутри файла uart.c??? OR> Если его аналоги спрятаны от доступа в классе, то они пользователю OR> не нужны.

[...]

HZ>> что нужно держать в голове) не выглядит "исчезающе малой"!!! OR> Ну так не показывай наружу всё! OR> На то и существует static в C, чтобы видимость имён ограничить OR> файлом, в котором они заданы.

Все это так. И в данном случае, это, конечно, выход для С. И все это (объявление внутренних программных элементов статическими) попытка сделать по

++ному. Т.е. сделать именно то, что на ++ получается нативно. И после этого еще не считать ++ную модель лучшей, чем сишную!

Но и тут при таком подходе в С два недостатка.

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

Во-вторых, и в-главных, такой подход красиво выглядит для таких достаточно больших и законченных модулей, как описанный UART, когда для него можно выделить отдельный файл. А что делать, когда модулей много и они не такие крупные и функционально законченные? Каждому отдельный файл? Делал я так! Именно пытался растолкать модули по разным файлам, помещая в каждый не более двух-трех (в среднем). В итоге получил под дюжину исходных файлов и примерно столько же заголовков. Проект тогда был около 8 кбайт (прошивка). Впоследствии этот же проект развивался далее, и программа была переписана под ... Все удобно разместилось в трех файлах при размере (прошивки) около 12 кбайт.

Резюме: обсуждение с общих методик скатилось на конкретные приемы, что, конечно, тоже интересно, но не настолько, тем более, что конкретные приемы у каждого свои, а методики - они тяготеют к общности, что придает обсуждению большую значимость и интерес.

Таким образом, (возвращаясь к исходной точке обсуждения) на С можно пытаться проектировать программу в С++ном стиле только путем размножения исходных файлов, что тащит за собой неудобство в работе и оверхед. Если этого не придерживаться, то тогда получаем ворох в глобальной области видимости (проблемы растут от размера программы, где-то, по экспоненте, имхо).

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

HZ>> 2. Используется один стек и для данных, и для адресов возвратов, что HZ>> вынуждает для указателя стека данных использовать убогий SP, из-за OR> Не намного хуже, чем у x86 в 16-битном режиме :-) Но и не лучше :-(( HZ>> которого HZ>> возникает приличный оверхед и по размеру, и по скорости. Кроме того, OR> Да нет, если стековый кадр нужен, то в прологе порождается OR> frame pointer на Y и дальше всё "как обычно". Если стековый кадр не OR> нужен, то Y используется как хочется.

А как тогда быть с прерываниями? Т.е. вот вошли в функцию, скопировали SP в Y, начали использовать Y, и тут - бац! - прерывание! Какой поинтер будет использоваться в прерывании?

[...]

BP>>> никакие указатели и обойдется простым (r)call. Ы ? (c) OR.

HZ>> Не знаю, что такое "Ы", поэтому не могу ничего на это ответить. OR> "Ы?" это такой эмоциональный аналог "ну и?"

Хм, никогда бы не подумал.

HZ>> остальной части абзаца комментарий следующий: HZ>> В энный раз повторяю: все зависит от конкретных условий!!! OR> О чём и разговор - в огромном количестве "конкретных условий" OR> за C++ могут быть только два аргумента - "не сбивать руку" OR> и "очень уж эта мысля понравилась". Остальные расписания "плюсов плюсов" OR> как-то мало в тех "конкретных условиях" дают.

Кому как... Но поскольку все уже высказались, то и... закончим, пожалуй?!

HZ>> По поводу количества аргументов выскажу свое субъективное мнение HZ>> (которое, впрочем, совпадает с мнением вполне серьезных дядек): HZ>> если параметров при HZ>> передаче более двух, то это уже повод задуматься о том, нет ли ошибки HZ>> проектирования; OR> memcpy(dst, src, len);

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

И заметь, я сказал: повод задуматься. Повод - не причина. :)

HZ>> если больше трех, то это причина задуматься о том же; OR> AT45D_write( chip_no, offset, buf, len);

Да, а у меня:

TDataFlash::ReadBuffer(word addr, byte N); TDataFlash::ReadMemory(word PageAddr, word ByteAddr);

И т.д. (реализация, кстати, у тебя есть :)

OR> ну у меня два чипа стоит. И разбивать это на OR> AT45_select(chip_no); OR> AT45_write(offset, buf, len);

А если два чипа, то и тем более классы рулят! :) Заводишь два объекта, при создании (в конструкторе) указываешь, какой порт и пин используются для формирования chipselect'а, чтобы потом при AT45_1.ReadMemory(...) этот пин автоматом дергался как надо. А при AT45_2.ReadMemory(...) дергался другой пин, соответствующий другому чипу. И не нужно туда селекты метать. И обращаться можно хоть через указатель.

Обычно удается найти альтернативный вариант, который не уступает по эффективности и удобству использования.

OR> неохота, тем более что всё равно есть ошибка проектирования, так как ^^^^^^^^^^^^^^^^^^^^^ OR> во второй функции три параметра.

Не издевайся! :)) Повод задуматься еще на означает ошибки.

OR> Можно, конечно, сделать "поток" AT45 с модификаторами вывода, OR> но это уже перебор :-)

Эт точно.

HZ>> если больше четырех, то тут почти наверняка что-то не так! OR> Три параметра -- _очень_ частое явление.

У кого как. Вот только что посмотрел несколько своих проектов, только в одно из них была одна глобальная функция с тремя аргументами. Могу проект предъявить, если не веришь?!

OR> Четыре - реже, но не пугает.

Редкий случай, и тут уже не повод, тут причина! У меня за все время пару раз были такие функции, но обе они выполняли то, что обычно в С делается с помощью макроса. Обе они были встраиваемыми - в этом большой смысл - не производится копирования аргументов, просто тело функции разворачивается в точке вызова, и вся эта пачка аргументов эффективно используется по месту. Т.е. в точности, как макрос, только с контролем типов.

OR> Больше 4 -- действительно нечасто.

Вот и я говорю, что в этом случае почти наверняка что-то не так.

[...]

HZ>> а во втором нельзя - приходится 0x1F явно грузить в r19, и уж только HZ>> затем 'and'. Вот эта загрузка и есть та дополнительная команда.

HZ>> Таким образом, даже тут, при _непосредственном_ использовании HZ>> члена-данного HZ>> не просматривается источника оверхеда из-за C++'ного указателя this! OR> А это ещё вопрос - почему именно так сделано. Надо весь код смотреть, OR> может если бы он 'c' в C++ варианте поселил в r24, то ему пришлось бы OR> в r4 селить что-то ещё более важное, которому иначе не нашлось бы вверху OR> места именно из-за this :-))

На первый взгляд это и есть причина. Но я попробовал добавить в сишный вариант указатель в параметры, чтобы тоже не влезло в регистры, так компилятор все равно юзает r24, а указатель этот просто копирует из регистровой пары, сохранив ее в стеке в прологе (т.е. возникает то самое пресловутое копирование указателя и сохранение/восстановление регистровой пары в стеке).

Кстати, при объявлении функции-члена с модификатором __z стек для передачи не используется - this-то в Z помещается. И в обоих вариантах - и сишном, и

++ном Z указывает на 'rpl' и используется одинаково.

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

Так что, про оверхед тут говорить не приходится - все на уровне, как уже говорилось, разброса качества работы оптимизатора, и определяется не столько языком, сколько задачей.

OR> wbr,

Блин, я с этой дискуссией никак не могу толком взяться за изучение gcc (известно для чего ;-))

...so long!

### Если мужчина просит руки женщины, значит ему надоела своя.

Reply to
Harry Zhurov

Tue Sep 23 2003 17:14, Harry Zhurov wrote to Oleksandr Redchuk:

HZ>>> void uartInit(BYTE* Rx_buf, HZ>>> BYTE Rx_size, HZ>>> BYTE* Tx_buf, HZ>>> BYTE Tx_size, HZ>>> BYTE Baud_rate);

OR>> Я не понял - почему тут куча параметров, а у конструктора OR>> ниже только baud rate? Значит, это _разные_ по поведению OR>> системы, если там конструктор распределяет себе буфера по своему OR>> усмотрению.

Именно.

HZ> По функциональности одинаковые. Просто в сишном варианте все сделано HZ> в традициях С: работа с аппаратным UART'ом, кольцевые буфера, HZ> функциональность протокола обмена пакетами и прочее "живет" отдельно, и HZ> весь модуль представляет собой конгломерат этих частей. В плюсатом HZ> варианте все эти детали инкапсулированы внутри класса. Соответственно, на HZ> С вызывается функция, которая должна проинитить порт, ну и уж заодно, HZ> чтобы не делать две инициализирующие функции, т.к. и одной-то много, она HZ> инитит тот кусок, который отвечает за буфера. В плюсатом варианте все HZ> делается в конструкторах объемлющего и вложенных объектов, поэтому HZ> снаружи остается только передать то, что заранее никак неизвестно - HZ> скорость.

Ровно с тем же успехом можно было написать _одну_ функцию uart_init (U16 baud) на С, а все остально скрыть внутри файла "uart.c".

Давай будем сравнивать яблоки с яблоками.

HZ>>> Вот это все "живет" в глобальном пространстве имен. Там еще пара OR>> ПОЧЕМУ? OR>> Почему бОльшая часть этого не может быть static внутри файла uart.c??? OR>> Если его аналоги спрятаны от доступа в классе, то они пользователю OR>> не нужны.

HZ> [...]

HZ>>> что нужно держать в голове) не выглядит "исчезающе малой"!!! OR>> Hу так не показывай наружу всё! OR>> Hа то и существует static в C, чтобы видимость имён ограничить OR>> файлом, в котором они заданы.

HZ> Все это так. И в данном случае, это, конечно, выход для С. И все это HZ> (объявление внутренних программных элементов статическими) попытка HZ> сделать по ++ному.

Точнее это способ корректно пользоваться возможностями, предоставляемыми языком С. Другое дело, что не далеко не все программисты этому обучены. Я как-то смотрел код некоторых э-э-э, программистов. "-ать, -ать, -ать" - привычно повторило эхо. :-\ Проще все переписать.

HZ> Т.е. сделать именно то, что на ++ получается нативно. HZ> И после этого еще не считать ++ную модель лучшей, чем сишную!

Стоп, стоп, стоп. Если мы хотим сравнивать С++ и С, то надо сравнивать _аналогичные_ подходы.

HZ> Hо и тут при таком подходе в С два недостатка.

HZ> Во-первых, при обращении к переменной, инкапсулированной в модуле HZ> (единице трансляции), придется либо делать ее открытой, либо вводить HZ> функцию доступа.

Либо вводить макрос-псевдофункцию для доступа и эмулировать пространства имен префиксами.

Пример:

--------------------------------------- "rem.h"

--------------------------------------- extern U8 rem_oops; #define rem_set_oops(val) (rem_oops = val) #define rem_get_oops() rem_oops

---------------------------------------

--------------------------------------- "rem.c"

--------------------------------------- U8 rem_oops;

---------------------------------------

--------------------------------------- "bla-bla-bla.c"

--------------------------------------- if(!rem_get_oops() && is_it_good_time()) { rem_set_oops(OOPS_TIME); }

--------------------------------------- Кстати, это будет эффективней чем С++.

HZ> ++ предоставляет простой и логичный способ достичь защищенности HZ> без потери эффективности.

Hе понял. Как это без потери эффективности? Для доступа к защищенной переменной на С++ придется использовать функцию - член класса. Для доступа к static переменной на С придется использовать функцию.

Где потеря эффективнсти?

HZ> Во-вторых, и в-главных, такой подход красиво выглядит для таких HZ> достаточно больших и законченных модулей, как описанный UART, когда для HZ> него можно выделить отдельный файл. А что делать, когда модулей много и HZ> они не такие крупные и функционально законченные? Каждому отдельный файл?

Да. Я именно так и делаю.

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

И всего-то дюжина файлов. :-)))

28 *.с + 5 *.asm + 38 заголовков для проекта на 16К кода. Hикаких проблем. IMHO это больше зависит от личных пристрастий программиста, не более того. Я, например, не могу сказать чей подход правильней.

HZ> Таким образом, (возвращаясь к исходной точке обсуждения) на С можно HZ> пытаться проектировать программу в С++ном стиле только путем размножения HZ> исходных файлов, что тащит за собой неудобство в работе и оверхед.

Извини, но я не вижу ни неудобства, ни оверхеда.

HZ> Если HZ> этого не придерживаться, то тогда получаем ворох в глобальной области HZ> видимости (проблемы растут от размера программы, где-то, по экспоненте, HZ> имхо).

Просто надо придерживаться правил именования переменных.

Hе вижу большой разницы между.

rem_oops->set(OOPS_TIME) и rem_oops_set(OOPS_TIME)

HZ> Поэтому реально, afaik, придерживаются компромисса - пытаются HZ> рассовать по файлам наиболее взаимосвязанное, стремясь минимизировать HZ> количество файлов.

Hе надо минимизировать число файлов. Места в директории всем хватит. :) Hадо названия давать осмысленные.

HZ> Hо и того формализованного способа проектирования, который возможен в HZ> С++, тут уже нет! О чем и речь.

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

P.S. Я ничего не имею против С++, хороший и полезный язык. Hо и каких-либо особенных преимуществ по сравнению с _хорошо_ написанной программой на С тоже не усматриваю.

WBR, Юрий.

Reply to
Yuriy K

Tue Sep 23 2003 18:24, Yuriy K wrote to Harry Zhurov:

YK> Ровно с тем же успехом можно было написать _одну_ функцию YK> uart_init (U16 baud) на С, а все остально скрыть внутри файла "uart.c".

А если UARTов больше чем один? Что лучше: UARTInit(struct UART *, u16 baud_rate) или просто создать два обьекта класса UART?

OR>>> Почему бОльшая часть этого не может быть static внутри файла uart.c???

Использование static неправильно IMHO. Это сознательное ограничение возможностей. Получается неуниверсальный и труднопереносимый код, поддерживающий жестко заданное количество инстансов обьекта.

YK> Точнее это способ корректно пользоваться возможностями, предоставляемыми YK> языком С.

Hа С приходится делать те же самые по сути классы вручную, передавая в функцию указатель на структуру данных обьекта.

YK> Другое дело, что не далеко не все программисты этому обучены. Это да. Хорошо или плохо можно писать на чем угодно.

YK> Либо вводить макрос-псевдофункцию для доступа и эмулировать пространства YK> имен префиксами. YK> Кстати, это будет эффективней чем С++. YK> Просто надо придерживаться правил именования переменных.

Хорошо работает, если один программист. Попробуй заставить всех так делать, и чтоб еще не было конфликтов имен.

YK> И всего-то дюжина файлов. :-))) YK> Я, например, не могу сказать чей подход правильней.

Чем больше файл - тем лучше оптимизация :) But who cares.

YK> P.S. Я ничего не имею против С++, хороший и полезный язык. YK> Hо и каких-либо особенных преимуществ по сравнению с _хорошо_ написанной YK> программой на С тоже не усматриваю.

Попробуй, перейди на C++. Понравится и обратно на C не захочется :) VLV

Reply to
Vladimir Vassilevsky

Tue Sep 23 2003 19:20, Vladimir Vassilevsky wrote to Yuriy K:

YK>> Ровно с тем же успехом можно было написать _одну_ функцию YK>> uart_init (U16 baud) на С, а все остально скрыть внутри файла "uart.c".

VV> А если UARTов больше чем один? VV> Что лучше: UARTInit(struct UART *, u16 baud_rate) или просто создать VV> два обьекта класса UART?

Или

typedef enum {UART_1, UART_2, UART_OVER_CAN_1, UART_OVER_ETHERNET_1, ...} UART_ID;

void uart_init(UART_ID uart_id, U16 baud); void uart_put_char(UART_ID uart_id, U8 ch); ...

все детали реализации точно так же скрыты от пользователя.

Эстеты могут добавить

#define uart_alpha_init(a) uart_init(UART_1, a) #define uart_beta_init(a) uart_init(UART_2, a)

если очень хочется иметь разные имена для функций.

Или даже так: uart1_init(U16 baud); uart2_init(U16 baud);

Сильно зависит от конкретных условий применения.

UART-ы например могут быть _физически_ разные. Тогда два объекта одного класса вообще не получится сделать.

OR>>>> Почему бОльшая часть этого не может быть static внутри файла uart.c???

VV> Использование static неправильно IMHO.

static == private.

VV> Это сознательное ограничение возможностей.

Каких?

VV> Получается неуниверсальный и труднопереносимый код, VV> поддерживающий жестко заданное количество инстансов обьекта.

???

YK>> Точнее это способ корректно пользоваться возможностями, предоставляемыми YK>> языком С.

VV> Hа С приходится делать те же самые по сути классы вручную, передавая VV> в функцию указатель на структуру данных обьекта.

Да. Тем более в чем тогда разница?

YK>> Другое дело, что не далеко не все программисты этому обучены. VV> Это да. Хорошо или плохо можно писать на чем угодно.

YK>> Либо вводить макрос-псевдофункцию для доступа и эмулировать пространства YK>> имен префиксами. YK>> Кстати, это будет эффективней чем С++. YK>> Просто надо придерживаться правил именования переменных.

VV> Хорошо работает, если один программист. Попробуй заставить всех так VV> делать,

Префикс переменной = имени файла.

VV> и чтоб еще не было конфликтов имен.

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

YK>> И всего-то дюжина файлов. :-))) YK>> Я, например, не могу сказать чей подход правильней.

VV> Чем больше файл - тем лучше оптимизация :) VV> But who cares. You've got the point. :-))

YK>> P.S. Я ничего не имею против С++, хороший и полезный язык. YK>> Hо и каких-либо особенных преимуществ по сравнению с _хорошо_ написанной YK>> программой на С тоже не усматриваю.

VV> Попробуй, перейди на C++. Понравится и обратно на C не захочется :)

Это ж разбираться надо... Я вот бутлоадер дописываю под HС12 с перемещаемыми в ОЗУ подпрограммами прошивки флэша (на ассемблере, естественно), а вы тут с какими-то плюсами. Ж:-()~~~

WBR, Юрий.

Reply to
Yuriy K

Tue Sep 23 2003 19:41, Yuriy K wrote to Vladimir Vassilevsky:

YK>>> Ровно с тем же успехом можно было написать _одну_ функцию YK>>> uart_init (U16 baud) на С, а все остально скрыть внутри файла "uart.c".

VV>> А если UARTов больше чем один? VV>> Что лучше: UARTInit(struct UART *, u16 baud_rate) или просто создать VV>> два обьекта класса UART?

[....]

YK> UART-ы например могут быть _физически_ разные. Тогда два объекта одного YK> класса вообще не получится сделать.

Э, нет. Смысл ++ в том, чтобы иметь один и тот же интерфейс независимо от того, аппаратный ли это UART, или bit bang, или эмуляция через CAN/Ethernet/Bluetooth/и.т.д. Тем более что родительский класс UARTa - это FIFO, которое происходит от класса FILE. Делать все это на чистых С - слишком много надо помнить и всего везде менять, если требуется добавить или убавить устройство.

OR>>>>> Почему бОльшая часть этого не может быть static внутри файла OR>>>>> uart.c???

VV>> Использование static неправильно IMHO.

YK> static == private.

Только в случае единственного инстанса.

VV>> Это сознательное ограничение возможностей. YK> Каких?

Как создавать произвольное число обьектов? Удобно иметь универсальный класс UART, в котором везде где можно нет ограничений на количество создаваемых обьектов.

VV>> Hа С приходится делать те же самые по сути классы вручную, передавая VV>> в функцию указатель на структуру данных обьекта. YK> Да. Тем более в чем тогда разница? Это все равно, если нет наследования. Делать таким образом наследование получается криво и ненаглядно.

YK>>> Другое дело, что не далеко не все программисты этому обучены. VV>> Это да. Хорошо или плохо можно писать на чем угодно.

YK>>> Либо вводить макрос-псевдофункцию для доступа и эмулировать YK>>> пространства имен префиксами. YK>>> Просто надо придерживаться правил именования переменных.

VV>> Хорошо работает, если один программист. Попробуй заставить всех так VV>> делать,

YK> Префикс переменной = имени файла.

Ха. Мне уже приходилось приделывать к именам файла имена программистов:

vlv_rs232_main.dsp :)

VV>> и чтоб еще не было конфликтов имен.

YK> Попробуй заставить всех программистов обзывать свои классы YK> непересекающимися именами.

Можно принудительно ограничить области видимости. Hа то и ++.

VV>> Попробуй, перейди на C++. Понравится и обратно на C не захочется :) YK> Это ж разбираться надо...

Вот она, истинная причина.

YK> Я вот бутлоадер дописываю под HС12 YK> с перемещаемыми в ОЗУ подпрограммами прошивки флэша YK> (на ассемблере, естественно), а вы тут с какими-то плюсами. Ж:-()~~~

А мне потребовалось произвольное количество всяких мелких таймеров, живущих в фоне. Можно терпеливо и скорбно создавать их статически, а можно timer = new tTIMER(msec). Куда как удобнее.

VLV

Reply to
Vladimir Vassilevsky

Tue Sep 23 2003 20:49, Vladimir Vassilevsky wrote to Yuriy K:

YK>> UART-ы например могут быть _физически_ разные. Тогда два объекта одного YK>> класса вообще не получится сделать.

VV> Э, нет. Смысл ++ в том, чтобы иметь один и тот же интерфейс независимо VV> от VV> того, аппаратный ли это UART, или bit bang, или эмуляция через VV> CAN/Ethernet/Bluetooth/и.т.д. Тем более что родительский класс UARTa - VV> это VV> FIFO, которое происходит от класса FILE.

И как тут плюсы помогут?

VV> Делать все это на чистых С VV> - слишком много надо помнить и всего везде менять, если требуется VV> добавить или убавить устройство.

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

OR>>>>>> Почему бОльшая часть этого не может быть static внутри файла OR>>>>>> uart.c??? VV>>> Использование static неправильно IMHO. YK>> static == private. VV> Только в случае единственного инстанса.

Согласен. Только ведь количество инстансов для аппаратных ресурсов все равно определяется железом.

VV>>> Это сознательное ограничение возможностей. YK>> Каких?

VV> Как создавать произвольное число обьектов?

#define CHISLO_OBYEKTOV 255

VV> Удобно иметь универсальный класс UART, в котором везде где можно VV> нет ограничений на количество создаваемых обьектов.

Смысл? UART-ов в процессоре от этого больше не станет.

VV>>> Hа С приходится делать те же самые по сути классы вручную, передавая VV>>> в функцию указатель на структуру данных обьекта. YK>> Да. Тем более в чем тогда разница?

VV> Это все равно, если нет наследования. Делать таким образом наследование VV> получается криво и ненаглядно.

Естественно. Как часто нужно наследование в "embedded" задачах?

YK>>>> Либо вводить макрос-псевдофункцию для доступа и эмулировать YK>>>> пространства имен префиксами. YK>> Префикс переменной = имени файла. VV> Ха. Мне уже приходилось приделывать к именам файла имена программистов: VV> vlv_rs232_main.dsp :)

Это потому что имена файлов были неправильные. :-Р

VV>>> и чтоб еще не было конфликтов имен. YK>> Попробуй заставить всех программистов обзывать свои классы YK>> непересекающимися именами. VV> Можно принудительно ограничить области видимости. Hа то и ++.

Области видимости _чего_?

VV>>> Попробуй, перейди на C++. Понравится и обратно на C не захочется :) YK>> Это ж разбираться надо... VV> Вот она, истинная причина.

Дык о то ж. :-) Выяснять есть ли С++ под HС12, узнавать сколько стоит, выбивать деньги, а потом еще разбираться, как оно работает и обучать местных программистов. Кто должен быть счастлив? :-Р

Задач таких нет. Вот (если) буду писать GUI для управления трактором, тогда и займусь. Может быть.

VV> А мне потребовалось произвольное количество всяких мелких таймеров, VV> живущих в фоне. Можно терпеливо и скорбно создавать их статически, VV> а можно timer = new tTIMER(msec). Куда как удобнее.

Главное - чтобы куча не переполнилась.

А можно #define TIMER_MAX 10 и точно знать, сколько памяти использовано.

P.S. остается тот же.

WBR, Юрий.

Reply to
Yuriy K

Hello Dmitry.

23 Sep 03 15:36, you wrote to me:

По сравнению, с основным кодом ядра линукса - да.

Вообще-то для avr-g++ поддержка С++ занимает много меньше.

Alexey

Reply to
Alexey Boyko

Hello Vladimir.

23 Sep 03 20:49, Vladimir Vassilevsky wrote to Yuriy K:

VV>>> èÏÒÏÛÏ ÒÁÂÏÔÁÅÔ, ÅÓÌÉ ÏÄÉÎ ÐÒÏÇÒÁÍÍÉÓÔ. ðÏÐÒÏÂÕÊ ÚÁÓÔÁ×ÉÔØ ×ÓÅÈ ÔÁË VV>>> ÄÅÌÁÔØ, YK>> ðÒÅÆÉËÓ ÐÅÒÅÍÅÎÎÏÊ = ÉÍÅÎÉ ÆÁÊÌÁ. VV> èÁ. íÎÅ ÕÖÅ ÐÒÉÈÏÄÉÌÏÓØ ÐÒÉÄÅÌÙ×ÁÔØ Ë ÉÍÅÎÁÍ ÆÁÊÌÁ ÉÍÅÎÁ ÐÒÏÇÒÁÍÍÉÓÔÏ×: VV> vlv_rs232_main.dsp :)

:)

formatting link

×ÏÏÂÝÅ ÜÔÏ ÏpÇÁÎÉÚÁÃÉÏÎÎÙÅ ×ÏÐpÏÓÙ, ËÏÔÏpÙÅ ÔpÅÂ-ÓÑ × ÌÀÂÏÊ ÏpÇÁÎÉÚÁÃÉÉ Ó >1 pÁÚpÁÂÏÔÞÉËÁÍÉ.

VV>>> É ÞÔÏ ÅÝÅ ÎÅ ÂÙÌÏ ËÏÎÆÌÉËÔÏ× ÉÍÅÎ. YK>> ðÏÐÒÏÂÕÊ ÚÁÓÔÁ×ÉÔØ ×ÓÅÈ ÐÒÏÇÒÁÍÍÉÓÔÏ× ÏÂÚÙ×ÁÔØ Ó×ÏÉ ËÌÁÓÓÙ YK>> ÎÅÐÅÒÅÓÅËÁÀÝÉÍÉÓÑ ÉÍÅÎÁÍÉ. VV> íÏÖÎÏ ÐÒÉÎÕÄÉÔÅÌØÎÏ ÏÇÒÁÎÉÞÉÔØ ÏÂÌÁÓÔÉ ×ÉÄÉÍÏÓÔÉ. HÁ ÔÏ É ++.

naming conventions ÔpÅÂ-ÓÑ ×ÅÚÄÅ.

Alexey

Reply to
Alexey Musin

Hello "Harry.

23 Sep 03 16:14, you wrote to Oleksandr Redchuk:

HZ> Все же оптимизатор у ИАРа неплох! Тут было заявление, что скоро HZ> gcc догонит IAR. Очень сомневаюсь, что это произойдет скоро, и даже HZ> сомневаюсь, что это вообще произойдет - ИАР тоже на месте не стоит.

Hе. Hе догонит. Почти все что можно было сделать в avr-gcc - сделано. Что бы сделать лучше - нужно перелопачивать основной код gcc. А он не оптимален для 8 битных процессоров, и ради avr никто там копаться не будет.

(Кстати, Денис Чертыков все таки добился изменения в gcc register allocator'а на более современный, доступно опцией -fnew-ra, но особого прироста качества он не принес. Может со временем сделают лучше. Я сам колупался в gcc - все упирается в два с половиной указателя, ипать за ногу)

С ранними версиями ИАР gcc вполне успешно конкурировал. Hо ИАР не стоит на месте. а avr-gcc - стоит. Хотя для бесплатного компилятора - очень даже не плохо. Лучше, чем CodeVision и иже с ними.

Если очень хочется сравнить именно gcc и именно IAR, то лучше, имхо, сравнивать кодогенерацию для MSP430 или ARM.

Alexey

Reply to
Alexey Boyko

Hi Oleksandr.

22 Sep 2003, 22:26, Oleksandr Redchuk writes to "Harry Zhurov":

HZ> А что, их (UART'ов) много что-ли? А если один? OR> Если один, то у C++ вообще нет никаких преимуществ.

Комментарии удобные. ;) Проверка типов, вроде, построже. Я плохо знаю C++, но есть же там приятные фичи помимо классов и потоков.

HZ> Вопрос-то был: "Почему в С++ нет модулей?". OR> если в большинстве случаев достаточно их.

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

Dimmy.

Reply to
Dimmy Timchenko

Tue Sep 23 2003 21:46, Yuriy K wrote to Vladimir Vassilevsky:

YK> Это почему еще? Код для работы с железом все равно придется писать YK> примерно одинаковый, хоть на плюсах, хоть на бейсике, хоть на ассемблере.

Код для работы с железом - это ~5% задачи. Все остальное может быть вполне реюзабельным, универсальным и переносимым. Тот же UART на 90% состоит из FIFO и прочих аппаратно независимых интерфейсных частей, которые удобно оформить в универсальный класс.

YK>>> static == private. VV>> Только в случае единственного инстанса. YK> Согласен. Только ведь количество инстансов для аппаратных ресурсов YK> все равно определяется железом. VV>>>> Это сознательное ограничение возможностей. YK>>> Каких?

При очередной переделке проекта решили добавить еще один UART. (не суть важно, как он реализован в хардвере) Весь интерфейс переписывать?

VV>>>> Hа С приходится делать те же самые по сути классы вручную, передавая VV>>>> в функцию указатель на структуру данных обьекта. YK>>> Да. Тем более в чем тогда разница?

VV>> Это все равно, если нет наследования. Делать таким образом наследование VV>> получается криво и ненаглядно.

YK> Естественно. Как часто нужно наследование в "embedded" задачах?

Это весьма удобно, если несколько разных сущностей могут использоваться в одних и тех же целях. Hапример, ввод/вывод клавиатуры/LCD, взаимозаменяемый с вводом/выводом UARTa. Применяются одни и те же методы.

VV>>>> Попробуй, перейди на C++. Понравится и обратно на C не захочется :) YK>>> Это ж разбираться надо... VV>> Вот она, истинная причина.

YK> Дык о то ж. :-) Выяснять есть ли С++ под HС12, узнавать сколько стоит, YK> выбивать деньги, а потом еще разбираться, как оно работает и обучать YK> местных программистов. Кто должен быть счастлив? :-Р

YK> Задач таких нет. Вот (если) буду писать GUI для управления трактором, YK> тогда и займусь. Может быть.

Да даже менюшный ввод/вывод на двухстрочник удобнее писать на ++.

VLV

Reply to
Vladimir Vassilevsky

Wed Sep 24 2003 18:35, Vladimir Vassilevsky wrote to Yuriy K:

YK>> Это почему еще? Код для работы с железом все равно придется писать YK>> примерно одинаковый, хоть на плюсах, хоть на бейсике, хоть на YK>> ассемблере.

VV> Код для работы с железом - это ~5% задачи.

ОК. По крайней мере здесь пришли к согласию.

VV> Все остальное может быть VV> вполне реюзабельным, универсальным и переносимым. VV> Тот же UART на 90% состоит из FIFO и прочих аппаратно независимых VV> интерфейсных частей, которые удобно оформить в универсальный класс.

Или в универсальный модуль. Пока UARTы не появляются и пропадают во время работы разницы никакой.

YK>>>> static == private. VV>>> Только в случае единственного инстанса. YK>> Согласен. Только ведь количество инстансов для аппаратных ресурсов YK>> все равно определяется железом. VV>>>>> Это сознательное ограничение возможностей. YK>>>> Каких?

VV> При очередной переделке проекта решили добавить еще один UART. VV> (не суть важно, как он реализован в хардвере) VV> Весь интерфейс переписывать?

Зачем? Добавить еще один тип в UARD_ID и написать работу с этим новым типом. Переписывать существующий код не надо.

Hа С++ придется делать то же самое.

YK>> Естественно. Как часто нужно наследование в "embedded" задачах?

VV> Это весьма удобно, если несколько разных сущностей могут использоваться VV> в одних и тех же целях. Hапример, ввод/вывод клавиатуры/LCD, VV> взаимозаменяемый с вводом/выводом UARTa. VV> Применяются одни и те же методы.

Может быть. Пока не сталкивался.

WBR, Юрий.

Reply to
Yuriy K

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.