реклама на сайте
подробности

 
 
6 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Стиль программирования на Си, описание функции
sKWO
сообщение Mar 31 2008, 10:23
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Добрый день!
Столкнулся со следующей проблемой.
нашол код как сделать восемь таймеров написанный Alechin Jan.
Первое что кидается в глаза та это синтаксис мне непонятный.
Вот к примеру прототип функции остановки тай мера:
Код
void Stop_Timer(IN IDX timer);

ну и сама функция:
Код
/*--------------------------------------------------------------------------------------------*/
/* Процедура остановки таймера.                                                               */
/* Принимает:   номер таймера (0 - 7).                                                        */
/* Возвращает:  ничего не возвращает.                                                         */
/*--------------------------------------------------------------------------------------------*/
__monitor void Stop_Timer(IN IDX timer)
{
  Timer[timer].Timer_Ena = TIMER_DIS;
  return;
}

Непонятно что такое IDX? Ну IN понятно, направление, очень удобно.
IDX по ходу здесь беззнаковый чар.
Ну и соответственно вопрос:
Этот синтаксис возможен через какоето макроопределение?
Может кто знает, подскажите, уверен это интерессно не только мне.
Вот ещё пример
Код
void Start_Timer(IN IDX timer, IN WORD interval, IN pTIMER_FUNC pFunc = NULL, IN bool cycle = TIMER_ONCE);

Спасибо.


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Axxel
сообщение Mar 31 2008, 10:36
Сообщение #2


Частый гость
**

Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896



Цитата(sKWO @ Mar 31 2008, 16:23) *
Этот синтаксис возможен через какоето макроопределение?

Да, typedef, или через структуру.

Сообщение отредактировал Axxel - Mar 31 2008, 10:40


--------------------
Если боишься - не говори. если сказал - не бойся. ©
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 31 2008, 10:40
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Стиль жуткий, не надо так делать.

Цитата(Axxel @ Mar 31 2008, 14:36) *
Да, или через структуру.

Это как?
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 31 2008, 10:59
Сообщение #4


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата
Этот синтаксис возможен через какоето макроопределение?

да, и через макроопределение:

Код
#define CHAR char


и через typedef

Код
typedef char CHAR;


Но думаю что конкретно в вашем примере IDX задумывался быть перечислимым типом, объявленным через enum

Код
typedef enum
{
    TIMER1 = 0,
    TIMER2,
    TIMER3,
    .... ,
    TIMER_COUNT
} IDX;
Go to the top of the page
 
+Quote Post
sKWO
сообщение Mar 31 2008, 11:56
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(defunct @ Mar 31 2008, 14:59) *
да, и через макроопределение:

Код
#define CHAR char


и через typedef

Код
typedef char CHAR;


Но думаю что конкретно в вашем примере IDX задумывался быть перечислимым типом, объявленным через enum

Код
typedef enum
{
    TIMER1 = 0,
    TIMER2,
    TIMER3,
    .... ,
    TIMER_COUNT
} IDX;

Ага, спасибо. Чёта мучают сомнения нащёт квалификатора перечисления
Но тогда непонятно это (Его же стиль)
Код
OUT bool Wait_LCD_Ready(IN IDX c)

Да, тогда ещё вопрос :
Если возможности препроцессора ограничены, то лучше использовать typedef используя возможности компилятора? И в каких случаях предпочтительнее #define?
Если кому не тяжело , приведите конкретный пример чтобы компилятор проглотил!
Спасибо!

Цитата(Axxel @ Mar 31 2008, 14:36) *
Да, typedef, или через структуру.

ПОКАЖИ

Цитата(aaarrr @ Mar 31 2008, 14:40) *
Стиль жуткий, не надо так делать.

Возможно, но мне просто интерессно. Просто в голове не укладывается как ?!

Сообщение отредактировал sKWO - Mar 31 2008, 11:58


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
dxp
сообщение Mar 31 2008, 12:16
Сообщение #6


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(sKWO @ Mar 31 2008, 18:56) *
Да, тогда ещё вопрос :
Если возможности препроцессора ограничены, то лучше использовать typedef используя возможности компилятора? И в каких случаях предпочтительнее #define?

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 12:48
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



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

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

Почему-то приходится применять гораздо шире. Где не вижу тонкой грани?


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
Alechin
сообщение Mar 31 2008, 14:08
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 27-06-05
Из: Химки, Моск.обл.
Пользователь №: 6 334



Так как кусок кода мой - скажу как это описано у меня (то бишь в оригинале):


// Тип переменной, занимающей 1 байт (0..255).
typedef unsigned char BYTE;
#define MAX_BYTE ((BYTE)-1)

// Тип переменной-указателя на переменную, занимающую байт.
typedef BYTE * pBYTE;

//--------------------------------------------------------------------------------------------
// Тип индексной переменной (0..255);
typedef unsigned char IDX;
#define BAD_IDX ((IDX)-1)

//--------------------------------------------------------------------------------------------
// Тип переменной, занимающей 2 байта (0..65536).
typedef unsigned short WORD;
#define MAX_WORD ((WORD)-1)

// Макрокоманда получения значения младшего байта слова.
#define LO_BYTE(word) (BYTE)(word)

// Макрокоманда получения значения старшего байта слова.
#define HI_BYTE(word) (BYTE)((WORD)(word) >> 8)

// Макрокоманда формирования значения типа WORD из двух значений типа BYTE.
#define MAKE_WORD(lo, hi) (WORD)(((BYTE)(lo)) | ((WORD)(hi) << 8))

// Тип переменной-указателя на переменную, занимающую 2 байта.
typedef WORD * pWORD;

//--------------------------------------------------------------------------------------------
// Тип переменной, занимающей 4 байта (0..4 294 967 296).
typedef unsigned long int DWORD;

// Тип переменной-указателя на переменную, занимающую 4 байта.
typedef DWORD * pDWORD;

// Макрокоманда получения значения младшего слова двойного слова.
#define LO_WORD(dword) (WORD)(dword)

// Макрокоманда получения значения старшего слова двойного слова.
#define HI_WORD(dword) (WORD)((DWORD)(dword) >> 16)

// Макрокоманда формирования значения типа DWORD из двух значений типа WORD.
#define MAKE_DWORD(lo, hi) (DWORD)(((WORD)(lo)) | ((DWORD)(hi) << 16))

//--------------------------------------------------------------------------------------------
// Тип переменной, занимающей 8 байт.
typedef unsigned long long QWORD;

// Макрокоманда получения значения младшего двойного слова четверного слова.
#define LO_DWORD(qword) (DWORD)(qword)

// Макрокоманда получения значения старшего двойного слова четверного слова.
#define HI_DWORD(qword) (DWORD)((QWORD)(qword) >> 32)

// Макрокоманда формирования значения типа QWORD из двух значений типа DWORD.
#define MAKE_QWORD(lo, hi) (QWORD)(((DWORD)(lo)) | ((QWORD)(hi) << 32))

// Тип переменной-указателя на переменную, занимающую 8 байт.
typedef QWORD * pQWORD;

//--------------------------------------------------------------------------------------------
// Тип переменной-счетчика секунд.
typedef DWORD SECONDS_CNTR;
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 31 2008, 14:13
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Извиняюсь, что вклиниваюсь.
Цитата(sensor_ua @ Mar 31 2008, 18:48) *
Просветите, плз, откуда такая категоричная постановка?
Для переносимости кода. Потому, что компиляторы пишут обычно как можно ближе к стандарту языка программирования. А препроцессоры по большей части не стандартизованы (исключая может быть лишь #define и #include). И то, что работает на одном, не обязательно поймет препроцессор другого компилятора. Кроме того, препроцессор не проверяет типы данных и соответственно, оперируя его командами, можно допустить такие ошибки, которые потом "вылавливать" дольше и сложнее.
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 31 2008, 14:17
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(sKWO @ Mar 31 2008, 13:56) *
Чёта мучают сомнения нащёт квалификатора перечисления
Но тогда непонятно это (Его же стиль)
Код
OUT bool Wait_LCD_Ready(IN IDX c)

Правильно мучают.
Стиль действительно странный, не упирайтесь в него. Попробуйте переписать.

Для арифметики гораздо удобнее объявить типы с короткими именами, и которые будут говорить сами за себя:

Код
typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned long U32;
typedef unsigned long long U64;

typedef signed char S8;
typedef signed short S16;
typedef signed long S32;

typedef volatile unsigned char V8;
typedef volatile unsigned short V16;
typedef volatile unsigned long V32;
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 14:39
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Для переносимости кода.
...
IMNHO, совсем неубедительно. Именно перепроцессором разруливаю проекты на AVR (IAR/GCC) и LPC (RVDMK/IAR), имеющие общий API. Полезные макросы пишутся, естественно, так, чтобы портировалось корректно, очень многие функции параметризуются макроопределениями по шаблонам. На работе препроцессора завязано очень много, при этом несовместимости как-то не наблюдаетсяwink.gif


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 31 2008, 14:51
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(sensor_ua @ Mar 31 2008, 20:39) *
IMNHO, совсем неубедительно. Именно перепроцессором разруливаю проекты на AVR (IAR/GCC) и LPC (RVDMK/IAR), имеющие общий API. Полезные макросы пишутся, естественно, так, чтобы портировалось корректно, очень многие функции параметризуются макроопределениями по шаблонам. На работе препроцессора завязано очень много, при этом несовместимости как-то не наблюдаетсяwink.gif
Уже были и неоднократно пояснения почему typedef предпочтительнее #define. Пользуйтесь поиском. Вот, например, одна из недавних веток обсуждения http://electronix.ru/forum/index.php?showt...&hl=typedef
Go to the top of the page
 
+Quote Post
vshemm
сообщение Mar 31 2008, 15:08
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 167
Регистрация: 15-08-07
Пользователь №: 29 803



Есть замечательная книга Алена Голуба "Правила программирования на С\С++". Небольшая, где на доходчивых примерах описываются разного рода "тонкости" (авторские). Так там рекомендуется использовать препроцессор только тогда, когда это необходимо. Объясняется все просто: код, активно использующий препроцессор сложно читать, сопровождать и отлавливать ошибки. И, имхо, с этим трудно не согласиться smile.gif
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 15:23
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Уже были и неоднократно пояснения почему typedef предпочтительнее #define

Спасибо, но я неплохо понимаю, что такое typedef, ну и когда может быть полезно применить #define. Если рассматривать только typedef и #define, то в основном соглашусь с Вами. Только какое это имеет отношение к переносимости кода?

Цитата
Объясняется все просто: код, активно использующий препроцессор сложно читать, сопровождать и отлавливать ошибки

Если использование макроопределений, скажем, явно избыточно, не используются правила образования имен, то соглашусь. Также замечу, что без достойного инструмента, позволяющего "ходить" по коду не только по функциям и переменным, но и по макроопределениям, отлаживаться также может быть затруднительно. Но, если нотации определены и их придерживаются, а инструмент заточен, то всё путём.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
sKWO
сообщение Mar 31 2008, 16:51
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Спасибо, Ребята! Дисскусия разворачивается хорошая, ну и огромное спасибо автору кода!
Правда нету определения in и out.

Сообщение отредактировал sKWO - Mar 31 2008, 16:55


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 17:10
Сообщение #16


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Попробуй таки найти текстовым поиском "#define IN" и "#define OUT"
или "отбросить" их как нечто ненужноеwink.gif
#define IN
#define OUT
у меня, например, в кейле используется
#define __flash
чтобы код из IAR не трогать


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 31 2008, 17:12
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(sensor_ua @ Mar 31 2008, 23:10) *
Попробуй таки найти текстовым поиском "#define IN" и "#define OUT"
или "отбросить" их как нечто ненужноеwink.gif
#define IN
#define OUT
у меня, например, в кейле используется
#define __flash
чтобы код из IAR не трогать

А вот на такое безобразие препроцессор сругаться должен. Вообще-то #undef для этих целей существует wink.gif
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 17:26
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
А вот на такое безобразие препроцессор сругаться должен

Вот и найдётсяwink.gif
А #undef существует для случаев когда точно знаешь, что нужно нечто переопределить. Сложнее переопределить чего-нить типа
typedef enum bool{
false = 0,
true = -1
};


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 31 2008, 18:49
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(sensor_ua @ Mar 31 2008, 23:26) *
А #undef существует для случаев когда точно знаешь, что нужно нечто переопределить.
Дык
Код
#ifdef __flash
  #undef __flash
#endif

и всех делов smile.gif
Цитата(sensor_ua @ Mar 31 2008, 23:26) *
Сложнее переопределить чего-нить типа
Вот именно что "сложнее", потому и надежнее.
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 19:07
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Гыwink.gif Мне код перебивать не нужно. Мне как раз единожды написанное под яром нужно не править - у меня текст один для кейла и яра, а ненужные квалификаторы просто выбрасываются после разруливанияwink.gif
Цитата
потому и надежнее.

Тут в примере особо изощренный случай. Такое "надёжное" лучше бы не попадалось вовсе. Пример наглого использования умолчаний Си
bool is_leap(int year){
if(!(year%400))return true;
if(!(year%100))return false;
if(!(year%4))return true;
return false;
}
int Get_Days_In_Month(int month, int year){
return(Days_Array[month]+(month==2)?is_leap(year):0);
}
при таких объявлениях bool просто веселитsmile.gif


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
Lem
сообщение Mar 31 2008, 20:08
Сообщение #21


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 20-03-05
Пользователь №: 3 533



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

Правда, я лично использую его неправильно, надо отучаться...
Для маленьких проектов, например, для микроконтроллеров типа АВР, разницы никакой, но привычка переносится и на большие, а там проявляются все эти кажущиеся надуманными проблемы.
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 31 2008, 20:29
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
препроцессором не рекомендуется пользоваться

Простите, но кем и где не рекомендуется? В стандарте?
Цитата
во что разворачивается макроопределение выяснить практически нереально (достоверно)

ИМХО, это больше зависит от стиля написания и принятого механизма проверок.
ЗЫ Во встраиваемых устройствах до недавнего времени довольно часто приходилось экономить ОЗУ при достаточном объёме памяти программ. Грамотное использование препроцессора позволяет более рационально использовать память программ, высвобождая ОЗУ.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 31 2008, 22:07
Сообщение #23


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(vshemm @ Mar 31 2008, 19:08) *
Так там рекомендуется использовать препроцессор только тогда, когда это необходимо. Объясняется все просто: код, активно использующий препроцессор сложно читать, сопровождать и отлавливать ошибки.


Пишем, пишем...
Объявляем трехэтажный мат #define func_type_macro(arg1,arg2,arg3) .....
Применяем объявленный трехэтажный в 10-ти этажной конструкции нужное количество раз. В куске кода, размер которого никого не испугает.
..........................................
Отменяем #undef func_type_macro

В общем, я для себя решил, что если у меня накапливаются глобальные сложные дефайны, то это значит, что реализация идеи неправильная.
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 1 2008, 03:41
Сообщение #24


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(sensor_ua @ Mar 31 2008, 19:48) *
Просветите, плз, откуда такая категоричная постановка?

Уже неоднократно на эту тему проходились, повторять не охота, воспользуйтесь поиском.

Вкратце. Макроподстановка таит в себе опасность из-за того, что делается тупо, без контроля типов и контекста, в котром она производится. При этом пользователь видит одно, а получает другое. Наглядный пример тому - соседняя ветка про вычисления в макросах, когда пара лишних скобок меняла контекст выражения и вычисление выражения с этапа компиляции переносилось на этап выполнения программы, что предъявляло совершенно другие требования по потреблению стека, в частности. Причем все это происходит скрытно от пользователя, в этом и подлость.

Отсутствие анализа контекста несет еще косяки - недавно обсуждали: например, фирма IAR ввела для некоторых новых чипов AVR макроопределения в заголовочных файлах ioxxx.h типа

Код
#define N 2
#define C 0


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

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

Код
#define TRUE FALSE // счастливой отладки, суки

lol.gif

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

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

Цитата(sensor_ua @ Mar 31 2008, 19:48) *
Почему-то приходится применять гораздо шире. Где не вижу тонкой грани?

А вот мне не приходится. И все получается. Приходится применять только в рамках вышеописанного - для условной компиляции и простых подстановок при портировании.

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

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

Макросы-функции без проблем заменяются встраиваемыми (inline) функциями. Это на сегодняшний день штатно умеют уже не только С++, но и С компиляторы. По Стандарту.

Если требуются какие-то нетривиальные вычисления и надо, чтобы они гарантировано производились на этапе компиляции (во избежание оверхеда), то существует мнение (и я его придерживаюсь), что такие вещи лучше вообще выполнять внешними инструментами и подсовывать компилятору уже готовые значения (потому как компилятор - не калькулятор). Через опцию -D, либо вообще поместив их в отдельный файл, который включается в проект. При использовании систем сборки (make, scons) технических трудностей не возникает никаких. Да и с оболочками тоже проблем во многих случаях нет. В любом случае не слишком разумно заставлять пыжиться целочисленный препроцессор с его 32-битной арифметикой - он отомстит (что часто и происходит). smile.gif

Если все это вас не убедило, поищите в сети мнение авторитетного дяденьки Б.Страуструпа (автора языка С++), возможно, он подробнее объяснит. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Axxel
сообщение Apr 1 2008, 04:30
Сообщение #25


Частый гость
**

Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896



Цитата(sKWO @ Mar 31 2008, 17:56) *
ПОКАЖИ


typedef struct TYPE{
......
......
......
} TYPE

TYPE var;
......

Да, конечно, создание структуры созданием нового типа назвать нельзя.
Правильнее говорить "структура типа type" вот что я имел ввиду.
sKWO спросил, насколько я понял, "что может быть если где-то встречается нстнадартный тип"

Сообщение отредактировал Axxel - Apr 1 2008, 04:55


--------------------
Если боишься - не говори. если сказал - не бойся. ©
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Apr 1 2008, 05:53
Сообщение #26


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Уже неоднократно на эту тему проходились, повторять не охота, воспользуйтесь поиском.

Простите, но что искать? По слову макрос? Я тут довольно часто, но мимио видно всё интересное по теме пробежало.
Цитата
Макроподстановка таит в себе опасность

Я не спорю, что пользоваться нужно уметь, а тем более таких глупых вещей, как примере от IAR, не допускать (с примерчиком познакомился ранее просматривая хедеры).
Цитата
По этим причинам использование макроподстановок должно быть минимизировано до уровня минимально необходимого, без которого реально не обойтись.

А вот тут начинается полный субъективизм. Обратный пример - неинициализированные элементы структур и, как самые приятныеwink.gif варианты, неинициализированные указатели на функции и использование указателей на структуры в качестве формальных параметров функции. Необходимость выдерживать порядок инициализации приводит к ещё более "подлым" ошибкам, чем жесткое конфигурирование с использованием макроподстановок (ну нет шаблонов в Си). Но, ИМХО, всё это имеет право на использование, если это не самоцель.
Цитата
Макросы-литералы замечательно заменяются настоящими типизированными константами. При этом никакого оверхеда не возникает - если нет попытки взять адрес константного объекта или завести ссылку на него, то компилятор не будет его размещать в памяти. Правда, это относится к С++, где у констант по умолчанию внутреннее связывание.

К сожалению, это, IMHO, более желаемое, чем действительное. const переменная это все-таки переменная.
Цитата
то существует мнение (и я его придерживаюсь)

опять же всё субъективно. Если не понимать ограничений препроцессора, то можно и в самом простом ошибиться. (Я, например, для редких случаев сложных константных выражений применяю тесты на интерпретаторе Ch)

Цитата
Но, думается, сегодня уже нет проблем использовать плюсатый компилятор

К сожалению, есть.

Цитата
Некоторое время назад попался прикол (возможно байка

Аналогично
#define else ;


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Apr 1 2008, 06:16
Сообщение #27


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Пример winavr
Код
eeprom_read_block(&my_variable,&my_param,sizeof(my_variable));


Ну не хочу я стока писАть !!!

Код
#define eeread(Var,Param) eeprom_read_block(&Var,&Param,sizeof(Var))
..........................
eeread(my_variable,my_param);


Интересует субъективное мнение:
оправдано ли в данном случае применение макро?
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Apr 1 2008, 06:30
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(sensor_ua @ Apr 1 2008, 08:53) *
Простите, но что искать? По слову макрос? Я тут довольно часто, но мимо видно всё интересное по теме пробежало.


Я расскажу интересное! smile.gif Не далее как вчера час искал отсутствие фигурных скобок в макросе из двух команд, который использовался в if /else. На фоне какой-то непонятной потери синхронизации с JTAGом повеселился по полной программе. Сам себе клоун. sad.gif

Тем не менее сложные макросы использую, вариант с функциями inline не перекрывает всех возможных ситуаций. Использую один раз созданную конструкцию для организации доступа к переменным в протоколе обмена и переношу из проекта в проект, один раз отладив стиснув зубы smile.gif

Но создавать такое в каждом проекте - упаси Бог.

Для того, чтобы было понятно, о чем разговор, пример текста описания переменных.
В поддержку протокола в объект 'system' включаются 4 переменных со своими именами, и функциями, вызываемыми при чтении и записи. Все это разворачивается в массивы строк и указателей на функции.
Добавление переменной в протокол происходит за минуту максимум.

Код
IMPL_PROLOG(system)
  IMPL_VARIABLE(system, 0, "HTI 16V hose pumps",
                IMPL_GET dpr->tx_value=(long)COUNT_ELEMENTS(system_names); return;,
                IMPL_SET READ_ONLY
                           )
  IMPL_VARIABLE(system, 1, "Firmware version",
                IMPL_GET dpr->name=version; return;,
                IMPL_SET READ_ONLY
                )
  IMPL_VARIABLE(system, 2, "Objects quantity",
                IMPL_GET dpr->tx_value=(long)OBJECTS_QUANTITY; return;,
                IMPL_SET READ_ONLY
                )
  IMPL_VARIABLE(system, 3, "Heartbeat Period,s",
                IMPL_GET GET_HEARTBEAT,
                IMPL_SET SET_HEARTBEAT
                )
IMPL_EPILOG()


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Apr 1 2008, 06:33
Сообщение #29


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(sensor_ua @ Apr 1 2008, 09:53) *
К сожалению, это, IMHO, более желаемое, чем действительное. const переменная это все-таки переменная.


Еще добавлю примерчик
Код
static PROGMEM char array[3] = {'A','B','C'};
................................
char a;
a = array[0];


Winavr сделает a='A' , поскольку array[0] рассматривается как константное выражение.
Сделают ли то же самое компилеры с услужливым сервисом "чтения флеша" - не уверен.
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 1 2008, 07:01
Сообщение #30


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(sensor_ua @ Apr 1 2008, 12:53) *
А вот тут начинается полный субъективизм. Обратный пример - неинициализированные элементы структур и, как самые приятныеwink.gif варианты, неинициализированные указатели на функции и использование указателей на структуры в качестве формальных параметров функции. Необходимость выдерживать порядок инициализации...

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

Цитата(sensor_ua @ Apr 1 2008, 12:53) *
К сожалению, это, IMHO, более желаемое, чем действительное. const переменная это все-таки переменная.

Вернее - это констатный объект. Если нет необходимости размещать его в памяти (не берется адрес и нет ссылки на него), то никакой вменяемый компилятор этого делать не будет - именно для этой возможности в том же С++ специально ввели правило, согласно которому константные объекты имеют внутреннее связывание... Хорошо, не верите, давайте проверим. Поскольку тут форум по AVR, то на нем и будем тренироваться. Код:

Код
// file: slon.cpp

const int a = 10;

int f(int x)
{
    return x + a;
}


Комилятор - какой-то от IAR. v4.хх. Не суть важно. Результат:

Код
          const int a = 10;                                    
                                                                      
                                                                        
                              In segment CODE, align 2, keep-with-next
          int f(int x)                                                
                  ??f:                                                
          {                                                            
              return x + a;                                            
00000000   5F06               SUBI    R16, 246                        
00000002   4F1F               SBCI    R17, 255                        
00000004   9508               RET                                      
          }


Как видим, все замечательно получилось, ничего в памяти не размещается, никаких обращений к памяти, ессно, нет. Это в режиме ++. Отключаем его - в С режиме результат:

Код
                                                                  
                     In segment NEAR_I, align 1, keep-with-next    
                     REQUIRE `?<Segment init: NEAR_I>`            
const int a = 10;                                                
         a:                                                        
                     DS 2                                          
                     REQUIRE `?<Initializer for a>`                
                                                                  
                                                                  
                     In segment CODE, align 2, keep-with-next      
int f(int x)                                                      
         f:                                                        
{                                                                
     return x + a;                                                
  5F06               SUBI    R16, 246                              
  4F1F               SBCI    R17, 255                              
  9508               RET                                          
}                                                                
                                                                  
                     In segment NEAR_ID, align 1, keep-with-next  
         `?<Initializer for a>`:                                  
  000A               DW 10


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

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

Поведение можно сделать как в ++ варианте, снабдив объявление констатны квалификатором static:

static const int a = 10;

Результат аналогичен первому варианту:

Код
static const int a = 10;                                      
                                                              
                                                              
                     In segment CODE, align 2, keep-with-next  
int f(int x)                                                  
         f:                                                    
{                                                            
     return x + a;                                            
  5F06               SUBI    R16, 246                          
  4F1F               SBCI    R17, 255                          
  9508               RET                                      
}


Думается, что написать ключевое слово 'static' не является слишком обременительным.

Кстати, сделать в С++ поведение констант аналогичным С-шному можно сделать с помощью объявления их как 'extern'. Результат компиляции приводить не буду, поверьте, оно точно соотвествует вышеприведенному С без 'static'.

Цитата(sensor_ua @ Apr 1 2008, 12:53) *
К сожалению, есть.

И в чем они состоят? Для AVR хоть коммерческий IAR, хоть безплатный AVR-GCC давно уже поддерживают почти все фичи С++ (за исключением тяжелых, которые реально применять на AVR смысла нет).


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Apr 1 2008, 08:17
Сообщение #31


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Но это, повторяю, другое

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

для начала вменяемые компиляторы не будут ругаться на передачу в качестве фактического параметра функции const переменной, когда формальный параметр объявлен не const. В "прямоугольных" вариантах применения (таких как Вы показали) действительно интеллект компилятора может быть на высоте.
Цитата
Думается, что написать ключевое слово 'static' не является слишком обременительным.

Вы не поверитеwink.gif - использую описанные Вами приёмы и не стесняюсь
Цитата
И в чем они состоят?

Насчёт одинаково хорошо
http://www.klen.org/Projects/Embeded-gnu-t...last_build.html
http://www.klen.org/Projects/Embeded-gnu-t...gcc-cpp-how.txt
А насчёт нюансов использования, например, смотрим пост 7
http://electronix.ru/forum/index.php?showt...;p=247899&#
Не то, чтобы я против использования плюсов - этим нужно заниматься(С)
Но как раз реализации "плюсовости" у компиляторов гораздо более различны, нежели отклонения в работе их препроцессоров.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 1 2008, 09:28
Сообщение #32


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(sensor_ua @ Apr 1 2008, 15:17) *
Дальше бессмысленно обсуждать - лучше/хуже, видно/невидно и применять/не применять, рекомендуется/нерекомендуется суть разные вещи.

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

Цитата(sensor_ua @ Apr 1 2008, 15:17) *
для начала вменяемые компиляторы не будут ругаться на передачу в качестве фактического параметра функции const переменной, когда формальный параметр объявлен не const.


Вы про это:

Код
const int a = 10;
int b;

int g(int x, int y);

int main()
{
    g(a, b);
}


?

Если да, то вот результат:

Код
int main()
        main:
{
    g(a, b);
....               LDI     R30, LOW(b)
....               LDI     R31, (b) >> 8
8120               LD      R18, Z
8131               LDD     R19, Z+1
E00A               LDI     R16, 10
E010               LDI     R17, 0
........           CALL    ??g
}


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

Что не так?

Цитата(sensor_ua @ Apr 1 2008, 15:17) *
В "прямоугольных" вариантах применения (таких как Вы показали) действительно интеллект компилятора может быть на высоте.

Хорошо, покажите свои "треугольные" или "круглые" варианты, где в подобной ситуации (с константами) компилятор облажается. Давайте пример в студию, посмотрим его. Интересно.

Цитата(sensor_ua @ Apr 1 2008, 15:17) *
Вы не поверитеwink.gif - использую описанные Вами приёмы и не стесняюсь

Тогда не понятно, какую точку зрения отстаиваете.

Цитата(sensor_ua @ Apr 1 2008, 15:17) *

И что конкретно там не так? Я никакого криминала не увидел. Особенно, в части константных объектов - там вообще ни слова не нашел про это. Может, плохо искал? smile.gif

Цитата(sensor_ua @ Apr 1 2008, 15:17) *
А насчёт нюансов использования, например, смотрим пост 7
http://electronix.ru/forum/index.php?showt...=247899�

И что? Манглинг имен - обычное дело в С++, жить реально не мешает. И опять совсем не понял, как это мешает использовать константные объекты вместо макросов?

Цитата(sensor_ua @ Apr 1 2008, 15:17) *
Но как раз реализации "плюсовости" у компиляторов гораздо более различны, нежели отклонения в работе их препроцессоров.

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 1 2008, 12:40
Сообщение #33


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Lem @ Mar 31 2008, 22:08) *
как во что разворачивается макроопределение выяснить практически нереально (достоверно)

Как правило препроцессор идёт отдельным исполняемым файлом и/или у компилятора есть соответствующий ключик "выполнить только препроцессор".
И можно получить выход препроцессора и всё поразглядывать.



Да, очень много чего можно затолкать в enum-ы, inline-функции и т.п.
Да, в С++ есть ссылки, позволяющие уменьшить использование указателей и связанных с неправильным их применением ошибок (ударение на слове "неправильным", а не на слове "применением"). И т.д. и т.п.
Но, извините,
#define TRUE FALSE
и
#define SQR(x) x * x
это примеры вредительского и безграмотного применения макросов, а не их генетической ущербности.
Но на их базе строится рекомендация "использование макросов следует уменьшать в идеале до нуля", что, на мой взгляд, неправильно, как неправильны и рекомендации не использовать указатели (а почему тогда в стандарте оставили не только условную компиляцию, но и функциональные макросы, склейку и подстановку аргументов и оставили указатели?)

Так же как и с goto, который я использую редко и на форумах иногда сам привожу примеры, как можно обойтись без goto и при этом и сгенерированный код не растёт, и читаемость улучшается, но который я инода таки использую - так же и с макросами:
Используйте, не бездумно, голова дана именно для выбора нужного средства языка!
(Кстати, а какое средство языка можно использовать бездумно? Знаменитые примеры "индусского" кода написаны и без макросов, и без gotoи часто вообще на яве, изначально "лишённой недостатков С/С++")
Правильно и в нужном месте применённые макросы, на мой взгляд, только улучшают (не слишком хорошо формализуемый и очень вкусовой параметр) читаемость кода. Кончено, для людей, умеющих с ними обращаться (та же проблема с указателями).
Огрызок .h
Код
typedef WINAPI void (*DlPortWritePortUchar_t) (unsigned port, uint8_t d);
typedef WINAPI uint8_t (*DlPortReadPortUchar_t) (unsigned port);
typedef WINAPI void (*DlPortWritePortBufferUchar_t) (unsigned port, const uint8_t *pd, int len);

class lpt_dlportio_t : public lpt_io_t
{
public:
    lpt_dlportio_t(unsigned _base);
    ~lpt_dlportio_t();

    virtual uint8_t read(rd_offset offs);
    virtual void write(wr_offset offs, uint8_t d);
    virtual void write_data(const uint8_t *pd, int len);

private:
    HINSTANCE hdlportio;
#define _DL_PTR(_f_) _f_##_t _f_##_P
    _DL_PTR(DlPortWritePortUchar);
    _DL_PTR(DlPortReadPortUchar);
    _DL_PTR(DlPortWritePortBufferUchar);
#undef  _DL_PTR
}; // class lpt_dlportio_t


Огрызок .cpp
Код
lpt_dlportio_t::lpt_dlportio_t(unsigned _base)
    : lpt_io_t(_base), hdlportio(NULL)
{
    hdlportio = LoadLibrary("DLportIO.dll");
    if (hdlportio == NULL)
        throw error_win32_t(E_INVHARD, "Can't load port access library `DLportIO.dll'");

#define _DL_LOAD(_f_)\
        do {\
            _f_##_P = (_f_##_t)GetProcAddress(hdlportio, #_f_);\
            if(_f_##_P == NULL)\
                throw error_win32_t(E_INVHARD, "Can't load port access library `DLportIO.dll'"); \
        } while(0)

    _DL_LOAD(DlPortWritePortUchar);
    _DL_LOAD(DlPortReadPortUchar);
    _DL_LOAD(DlPortWritePortBufferUchar);
#undef _DL_LOAD

} // lpt_dlportio_t::lpt_dlportio_t


И не говорите мне, что этот текст надо переписать без макросов для облегчения чтения и сопровождения (представим себе, что понадобилось добавить ещё одну функцию из dlportio.dll и/или изменить обработку ошибки - в каком случае надо больше до-/пере-писывать руками и где при этом больше шансов ошибиться в одной из ветвей - в варианте с макросами или с прямым текстом?

И ещё пример на эту тему

http://www.telesys.ru/wwwboards/mcontrol/1...es/314290.shtml


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 1 2008, 12:48
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



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

В связи с этим вопрос. Как в IAR просмотреть результаты работы препроцессора. Например где можно увидеть результаты вычисления констант? В ряде случаев это реально помогло бы. smile.gif
Go to the top of the page
 
+Quote Post
Lem
сообщение Apr 1 2008, 13:07
Сообщение #35


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 20-03-05
Пользователь №: 3 533



одним из авторитетов для меня является Герб Саттер,ну, там ещё куча умных опытных людей, которые много поработали с БОЛЬШИМИ системами и знают, какова цена тех или иных ошибок при отладке и сопровождении проектов, создаваемых коллективами за длительные сроки и большие деньги
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 1 2008, 13:11
Сообщение #36


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(SasaVitebsk @ Apr 1 2008, 19:48) *
На данном этапе не планирую отказываться от этого средства языка. Возможно потом пересмотрю данное решение.

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

Цитата(SasaVitebsk @ Apr 1 2008, 19:48) *
В связи с этим вопрос. Как в IAR просмотреть результаты работы препроцессора. Например где можно увидеть результаты вычисления констант? В ряде случаев это реально помогло бы. smile.gif

Да, такое средство очень кстати и меня не раз выручало. Ключик:

Код
--preprocess=[c][n][l] file|directory
                Preprocessor output
                   c     Include comments
                   n     Preprocess only
                   l     Include #line directives


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 1 2008, 13:15
Сообщение #37


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(SasaVitebsk @ Apr 1 2008, 15:48) *
Как в IAR просмотреть результаты работы препроцессора. Например где можно увидеть результаты вычисления констант? В ряде случаев это реально помогло бы. smile.gif
Project->Options->C/C++ compiler->Preprocessor-> галочка Preprocessor output to file. Только результатов вычисления там не будет - вычисляет компилятор в процессе оптимизации. Можно завести глобальную переменную и присвоить ей значение макроса, а дальше смотреть в листинге какое значение в эту переменную заносится.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Apr 1 2008, 13:37
Сообщение #38


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Не следует путать приятное с полезным...

Не знаю о чём Вы, но я о том, что заявления, что что-то НЕ РЕКОМЕНДУЕТСЯ, стОит подкреплять не столько личным мнением/опытом (нисколько не умаляю Ваших достоинств), сколько какими либо ссылками на Стандарт.

Цитата
Тогда не понятно, какую точку зрения отстаиваете

Я считаю, что препроцессор - нужный и полезный инструмент. Да, огульное его применение не приветствуется, так как существует много описанных выше причин, по которым возникают ошибки. Я для супа использую ложку, а для бифштекса - нож и вилку. Я могу объяснить, почему вилкой есть суп не получится, но мне трудно объяснять ребёнку, почему нельзя есть бифштекс ложкой.
typedef и применение текстовых замен действительно очень похожи, и если нужен тип, то typedef предпочтительнее, чем текстовая подстановка, но ведь не просто так - они отличаются - свойства у typedef имеются, которых у текстовых подстановок нет. Препроцессор позволяет манипулировать с именами (склейка, подмена, удаление, индексация), что при отсутствии поддержки шаблонов на уровне самого языка является необходимым дополнением. Что касается сложных выражений, то применение препроцессора ограничено его ограниченными возможностями и он действительно не предупреждает о переполнениях и прочих глупостях. Но сложность бывает разная - где мы в уме считаем, где не прочь в столбик, а где и калькулятора не хватает. Потому рекомендации по отказу от применения препроцессора при любой возможности считаю необоснованными.
Цитата
Хорошо, покажите свои "треугольные" или "круглые" варианты, где в подобной ситуации (с константами) компилятор облажается. Давайте пример в студию, посмотрим его. Интересно.

Что касается константных объектов приведу пример, который говорит в пользу препроцессора как удобного инструмента
Это выдаёт ошибку в IAR
Код
typedef void (MY_FOO_TYPE)();
typedef struct {
  int a;
  int b;
  int c;
  MY_FOO_TYPE * foo;
} mytype;

void myfoo1(void);
void myfoo2(void);
#define sDefault_Value1 {   \
                       777, \
                         0, \
                        55, \
                    &myfoo1 \
}
#define sDefault_Value2 {   \
                       111, \
                       222, \
                      3333, \
                    &myfoo2 \
}


const int def1_aa = 777;
const int def1_bb = 0;
const int def1_cc = 55;
const MY_FOO_TYPE * def1_foo = &myfoo1;

mytype a = {0};

const mytype aaa = sDefault_Value1;
const mytype bbb = sDefault_Value2;
volatile int i;
int main(void){
  while(1){
    if(i == a.a){
      i = a.b;
      a = aaa; // ошибки нет
      a.a = def1_aa;
      a.b = def1_bb;
      a.c = def1_cc;
          a.foo = def1_foo;//!!!ошибка
//Error[Pe513]: a value of type "void () const *" cannot be assigned to an entity of type "void () *" D:\avrtst\avrtst\main.c 44

    }
    else{
      i = a.a;
      a = bbb;
    }

  }
  return 0;
}

void myfoo1(void){
;
}

Наверно правильно выдаёт

Цитата
А вот на препроцессор стандарта нет

п.6.10
http://upload.caxapa.ru/standards/ansi_c-i...c_9899-1999.pdf

Цитата
Да, такое средство очень кстати и меня не раз выручало. Ключик:

Отдельное спасибо


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 1 2008, 13:40
Сообщение #39


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(dxp @ Apr 1 2008, 15:11) *
Во всяком случае крайне желательно исключить повсеместное использование макросов препроцессора в качестве литералов и функций.
Ну в такой формулировке - с указанием где именно и без абсолютной категоричности - можно согласиться :-)
Но ведь обычно идёт разговор "запретить и всё тут, так как это источник ошибок".
Так человек, не разобравшийся в понятиях "побочный эффект" и "точка следования" рано или поздно накосячит с применением операторов ++, -- и ещё найдёт где. Но ведь никто не рекомендует отказаться от них и начать писать p = p + 1; Или уже рекомендуют? wink.gif


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 1 2008, 13:50
Сообщение #40


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(ReAl @ Apr 1 2008, 19:40) *
Как правило препроцессор идёт отдельным исполняемым файлом и/или у компилятора есть соответствующий ключик "выполнить только препроцессор".

Это где такое правило? В GCC? Рад за него. В IAR с некоторых пор появился ключик. А вот в используемом мной сейчас VDSP такого удовольствия нет (не нашел). Т.ч. тут как повезет.

Цитата(ReAl @ Apr 1 2008, 19:40) *
Да, очень много чего можно затолкать в enum-ы, inline-функции и т.п.

Именно! smile.gif И все, что можно туда затолкать, не надо пихать в макросы. Об этом и спич.

Цитата(ReAl @ Apr 1 2008, 19:40) *
Но, извините,
#define TRUE FALSE

Да это я вообще в качестве хохмы привел, не апеллируя к этому примеру, как к аргументу. Просто этот пример наглядно демонстрирует мощь препроцессора как дестуктивного средства, только и всего.

Цитата(ReAl @ Apr 1 2008, 19:40) *
это примеры вредительского и безграмотного применения макросов, а не их генетической ущербности.

Как насчет вышеприведенного примера про

Код
#define I 7
#define N 2
#define C 0

?

А ведь это не лохи какие-то делали, а вполне серьезная и уважаемая фирма IAR Systems, которая выпускает очень достойные продукты. Замечательные грабли. Замечательный пример той же самой деструктивной мощи. Да, препроцессор обладает известной гибкостью в силу своих свойств по текстовой подстановке, но это палка о двух концах. Не стоит злоупотрелять ею.

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

Цитата(ReAl @ Apr 1 2008, 19:40) *
Но на их базе строится рекомендация "использование макросов следует уменьшать в идеале до нуля",

Да. Но идеал недостижим. Поэтому препроцессор останется.

Цитата(ReAl @ Apr 1 2008, 19:40) *
(а почему тогда в стандарте оставили не только условную компиляцию,

Потому, что для нее нет адекватной замены.

Цитата(ReAl @ Apr 1 2008, 19:40) *
но и функциональные макросы, склейку и подстановку аргументов

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

Цитата(ReAl @ Apr 1 2008, 19:40) *
и оставили указатели?)

Указатели из другой оперы, не надо все в кучу валить. Еще спроси (ехидно так), зачем оставили ассемблер - там тоже можно при невнимательном обращении наворотить. smile.gif


Цитата(ReAl @ Apr 1 2008, 19:40) *
Так же как и с goto, который я использую редко

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

Цитата(ReAl @ Apr 1 2008, 19:40) *
так же и с макросами:
Используйте, не бездумно, голова дана именно для выбора нужного средства языка!

Осталось найти, как добраться до головы иаровских разрабов, соорудивших макросы, приведенные выше. smile.gif Если есть возможность разложить грабли - они будут разложены. Раньше или позже, чаще или реже. Желательно, чтобы это было реже. Для этого использование препроцессора надо свести к минимуму, о чем только и речь. Никто не призывает отказаться от него вообще - это, повторяю, нереально. Чего в крайности кидаться.

Цитата(ReAl @ Apr 1 2008, 19:40) *
(Кстати, а какое средство языка можно использовать бездумно? Знаменитые примеры "индусского" кода написаны и без макросов, и без gotoи часто вообще на яве, изначально "лишённой недостатков С/С++")

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

Цитата(ReAl @ Apr 1 2008, 19:40) *
И не говорите мне, что этот текст надо переписать без макросов для облегчения чтения и сопровождения (представим себе, что понадобилось добавить ещё одну функцию из dlportio.dll и/или изменить обработку ошибки - в каком случае надо больше до-/пере-писывать руками и где при этом больше шансов ошибиться в одной из ветвей - в варианте с макросами или с прямым текстом?

Это большой вопрос, как лучше, пример не убеждает. Насчет руками - про рефакторинг слышал? Кроме того, тут пример очень осторожного использования - определение макроса лежит прямо тут же, все перед глазами. Но не дай бог кто-нить вздумает использовать такое же имя _DL_PTR в своей программе. Будет удивлен. smile.gif Т.ч. тут тоже есть, что обсудить.

Цитата(ReAl @ Apr 1 2008, 20:40) *
Ну в такой формулировке - с указанием где именно и без абсолютной категоричности - можно согласиться :-)
Но ведь обычно идёт разговор "запретить и всё тут, так как это источник ошибок".

Это где это сказано, что "запретить" и все тут? Сказано было, свести к минимуму.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 1 2008, 14:43
Сообщение #41


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(dxp @ Apr 1 2008, 16:50) *
Осталось найти, как добраться до головы иаровских разрабов, соорудивших макросы, приведенные выше. smile.gif
Да фиг с ними, с разработчиками. Ну достучишься, и "миллионы строк кода уже написанного, отлаженного и работающего кода сразу перестанут компилироваться" wink.gif
Код
#ifdef I
#undef I
#endif
#ifdef N
#undef N
#endif
#ifdef C
#undef C
#endif
Добавлять сразу после #include <ioavr.h>
Кстати, эти же грабельки перекочевали и в заголовочники avr-libc.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 1 2008, 14:51
Сообщение #42


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(dxp @ Apr 1 2008, 15:50) *
Это где такое правило? В GCC? Рад за него.
Во-первых, "как правило" != "существует правило", во вторых, из правил есть исключения.
Необходимость выдавать ассемблерный листинг тоже нигде не прописана, но как правило эта возможность имеется.
На моей памяти большинство компиляторов позволяли просмотреть выдачу препроцессора.

Цитата(dxp @ Apr 1 2008, 15:50) *
Как насчет вышеприведенного примера про
Код
#define I 7
#define N 2
#define C 0

Ну что я скажу... У gcc в этом месте SREG_I, SREG_N и так далее.
Солидная фирма, не солидная - а бывает и на старушку прорушка.


Цитата(dxp @ Apr 1 2008, 15:50) *
Потому, что для нее нет адекватной замены.
Я спросил не "почему условную компиляцют оставили", а "почему вместе с ней оставили функциональные макросы, склейку, ..."

Цитата(dxp @ Apr 1 2008, 15:50) *
Совместимость и преемственность. Попробуй убери что-нить из этого - миллионы строк кода уже написанного, отлаженного и работающего кода сразу перестанут компилироваться.
Какого кода??? С++ ?
А какого лешего компилировать С-код С++-компилятором?
Или тогда решили, что всё, С-компиляторы больше никто не будет писать и даже развивать, и поэтому для сопровождения С-кода надо в С++ оставить явно вредные вещи? Могли бы в С++ режиме и устранить "огромный недостаток". Тем более, что в мелких, неочевидных и местами обидных случаях С++ таки сильно отличается от С (например, литерал 'я' в языке С имеет тип int а в С++ имеет тип char).


Цитата(dxp @ Apr 1 2008, 15:50) *
Указатели из другой оперы, не надо все в кучу валить. Еще спроси (ехидно так), зачем оставили ассемблер - там тоже можно при невнимательном обращении наворотить. smile.gif
А где ассемблер в стандарте языков С/С++ ??? laughing.gif


Цитата(dxp @ Apr 1 2008, 15:50) *
Для этого использование препроцессора надо свести к минимуму, о чем только и речь. Никто не призывает отказаться от него вообще - это, повторяю, нереально. Чего в крайности кидаться.
Коренное отличие многих среств языка от средств препроцессора в том, что с ними код читается без подводных граблей. Сразу видно, как используется средство, сразу понятно, что тут можно ожидать. А вот с препроцессором оно несколько не так.
Так в том-то и дело, что агитаторы за предельную минимизацию применения указателей а то иногда и тернарной операции говорят то же самое - "неочевидно, непонятно, в отличие от массивов, ссылок и if/else". И часто при этом столь же категоричны, как и в случае с goto - "не должно быть вообще", "по нашему стандарту предприятия goto запрещены". Так что кидаюсь в крайности не я.


Цитата(dxp @ Apr 1 2008, 15:50) *
Это большой вопрос, как лучше, пример не убеждает. Насчет руками - про рефакторинг слышал?
Это как - я добавляю в описание класса поле, а в конструкторе сразу по кнопочке "сделайте мне красвиво" сгенерируется для него
Код
нужное_имя = (нужный_тип)GetProcAddress(hdlportio, нужная_строка);
            if(нужное_имя == NULL)
                throw error_win32_t(E_INVHARD, "Can't load port access library `DLportIO.dll'");
Или всё же придётся ручками это делать?


Цитата(dxp @ Apr 1 2008, 15:50) *
Кроме того, тут пример очень осторожного использования - определение макроса лежит прямо тут же, все перед глазами. Но не дай бог кто-нить вздумает использовать такое же имя _DL_PTR в своей программе. Будет удивлен. smile.gif Т.ч. тут тоже есть, что обсудить.
Получит предупреждение о переопределении и сразу увидит что и где конфликтует.
Если код пишет так, что предупреждения валят десятками на каждый файл и поэтому отключил без разбору все предупреждения - то не помогут никакие ограничения - наксоячит.

Цитата(dxp @ Apr 1 2008, 15:50) *
Это где это сказано, что "запретить" и все тут? Сказано было, свести к минимуму.
Ну, ты не самый бескомпромиссный борец с препроцессором :-) И то считаешь, что "в идеале исключить вообще".
Я же считаю, что "в идеале" его может и неплохо бы заменить чем-то более грамотным, но оно почти наверняка будет более сложным и менее удобным (эти два фактора могут не уменьшить глюкодромистость, а увеличить), поэтому пусть лучше остаётся как есть и как с любым инструментом - его нужно знать, чтобы пользоваться правильно. А для этого нужно пользоваться. А чтобы было меньше отрезанных пальцев - не убирать с кухни ножи, а учиться ими пользоваться тогда, кода это надо и не махать ими, показывая, как летали листья. Но не говорить, что есть открывашки, консервные ножи и хлеб можно купить уже нарезанным, поэтому применение ножей
Цитата(dxp @ Mar 31 2008, 14:16) *
нужно свести к минимуму, в идеале исключить вообще. Но на практике это не удается сделать, поэтому приходится жить с ним. По большому счету ... имеет смысл использовать только
в затупленном виде для простеньких вещей типа намазывания масла.
Просто нужно учить тому, что каждый инструмент нужно использовать с умом. А не рекомендовать "минимизировать до отсутствия", так как пока научитесь - можете пораниться. А уж сколько людей ими убито... rolleyes.gif


Цитата(Сергей Борщ @ Apr 1 2008, 16:43) *
Кстати, эти же грабельки перекочевали и в заголовочники avr-libc.
Разве? Там ведь в common.h сидят SREG_*
Хотя, мне кажется, желание "облегчить переход с IAR" у них инода избыточное, могли и добавить односимвольные.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 1 2008, 20:44
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(dxp @ Apr 1 2008, 16:50) *
А вот в используемом мной сейчас VDSP такого удовольствия нет (не нашел). Т.ч. тут как повезет.

Самостоятельные препроцессоры "C" не редкость, да и тем-же GCC прогнать можно... Посему на везение уповать совсем незачем smile.gif.


Цитата(ReAl @ Apr 1 2008, 17:51) *
А какого лешего компилировать С-код С++-компилятором?

А почему-бы и нет? Есть свои приятственные фичи в C++ компиляторах и для почти сишного кода. А как, например в смешанном коде без немерянных извращений работать с плюсовым кодом?
Лично я в большинстве случаев так и поступаю.


Цитата(ReAl @ Apr 1 2008, 16:40) *
Но ведь никто не рекомендует отказаться от них и начать писать p = p + 1; Или уже рекомендуют? wink.gif

Рекомендуют smile.gif С полгода назад на форуме проскаивала ссылка на переводную статью по "правильному стилю" именно с такой рекомендацией. У многих сей опус вызвал одобрение smile.gif. Я естественно, не мог смолчать - возражал...


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 1 2008, 22:17
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(zltigo @ Apr 2 2008, 00:44) *
Рекомендуют smile.gif

smile.gif А мне так понравилось. По сравнению с Паскалем, к примеру. smile.gif

А с другой стороны - сомневаешься, напиши так, чтобы сомнений не было. smile.gif

Всётаки выбор - великое дело. Зачем самих себя ограничивать изначально. Сталкиваешься с граблями (своими), анализируешь, применяешь так, чтобы в дальнейшем не наступать. Так свой подход вырабатывается. А написание прог для совместного использования, или для постороннего использования, - всётаки сложная задача требующая своих подходов. Я, чаще всего, заимствованное переписываю под себя.

Тем не менее, с учётом данной дискуссии, сделаю выводы и обдумаю все ваши предложения. Попробую переосмыслить. А то действительно проблемы некоторые уже возникали. А всётаки было бы неплохо иметь элемент языка, который бы определял константы под которые гарантированно не выделяется память и которые вычисляются строго на этапе компиляции. Для IBM, экономия памяти не стоит как задача, а вот для мелкоAVRов былобы неплохо.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Apr 2 2008, 06:58
Сообщение #45


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(SasaVitebsk @ Apr 2 2008, 01:17) *
По сравнению с Паскалем, к примеру. smile.gif


Анафема тому Паскалю, который не поддерживает функции inc(N,M), dec(N,M) smile.gif
А насчет пред/пост инкремента, например, действительно генератор граблей. Но пользоваться приятно... до тех пор, пока есть уверенность в адекватной трансляции.
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 2 2008, 09:58
Сообщение #46


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(ReAl @ Apr 1 2008, 15:40) *
Но ведь никто не рекомендует отказаться от них и начать писать p = p + 1; Или уже рекомендуют? wink.gif

Delphi'сты рекомендуют smile.gif

Цитата(dxp @ Apr 1 2008, 15:50) *
Как насчет вышеприведенного примера про
Код
#define I 7
#define N 2
#define C 0

?

Я еще люблю применять
#define K 1024
#define M K*K

Просто кому придет в голову объявить переменную ОДНОЙ ЗАГЛАВНОЙ буквой?

Цитата(SasaVitebsk @ Apr 2 2008, 00:17) *
smile.gif А мне так понравилось. По сравнению с Паскалем, к примеру. smile.gif

++ / -- - просто создан для индексации массивов.
тоже неплохо смотрится в условиях.

а повсеместно тыкать ++ / -- ни ни, я отдаю предпочтение p += 1 вместо ++;
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Apr 2 2008, 10:15
Сообщение #47


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(defunct @ Apr 2 2008, 12:58) *
Delphi'сты рекомендуют
Они сишникам не указ, и даже не авторитет.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 2 2008, 11:55
Сообщение #48


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(zltigo @ Apr 1 2008, 22:44) *
Самостоятельные препроцессоры "C" не редкость, да и тем-же GCC прогнать можно... Посему на везение уповать совсем незачем smile.gif.
Тут можно спорить о возможном несовпадении (один из них или оба могут не польностью соответствовать стандрату и проверка одним другого будет неадекватной). Но в целом он чаще есть, чем его нет. Я их даже эпизодически прикручивал для своих нужд (например, в pldasm какие-то кусочки пихал для облегчения написания).

Цитата(zltigo @ Apr 1 2008, 22:44) *
А почему-бы и нет? Есть свои приятственные фичи в C++ компиляторах и для почти сишного кода. А как, например в смешанном коде без немерянных извращений работать с плюсовым кодом?
Лично я в большинстве случаев так и поступаю.

Это если говорить о сложившейся ситуации. И я тоже так делаю иногда, хотя и inline-функции, и объявление переменных по месту, включая счётчики в циклах for - есть в C99, просто до сих пор не все поддерживают. Да и в С99 есть не менее вкусная возможность инициализировать элементы структур/массивов по имени, в С++ этого нет. Так что... Где найдёшь, где потеряешь...

А если говорить на момент "до того", когда язык С++ только сбивался и ещё и люди не привыкли пользоваться "С-совместимыми" расширениями С++, и "массы текстов" не набралось, то кто мешал "таки повыкидывать из С++ тяжкое наследие С, не приносящее ничего, кроме вреда"?
По поводу смешанных проектов - никто не мешает весь С-текст держать в отдельных файлах, компилировать в С-режиме со всеми функциональными макросами, а потом линковать с С++ - программой, скомпилированной в С++ режиме.
Ввели бы для условной компиляции что-то как-бы похожее, но интегрированное в язык, а не являющееся отдельным проходом. Как результат в условии компиляции можно было бы применять и enum-определённые константы и т.п. Кто мешал? И не было бы споров smile.gif Ну скучал бы я по старым добрым макросам smile.gif


Цитата(_Pasha @ Apr 2 2008, 08:58) *
А насчет пред/пост инкремента, например, действительно генератор граблей.
Где? Как?
Может, генератором граблей есть голова пишущего, не разобравшаяся в побочных эффектах и точках следования?
Если так, то надо требовать изменения консти стандарта С таким образом, чтобы все переменные по умолчанию были volatile, так как от непонимания этого момента "глюков" ещё больше.
Ну или просто компилировать свои программы с выключенной оптимизацией.


Цитата(defunct @ Apr 2 2008, 11:58) *
а повсеместно тыкать ++ / -- ни ни, я отдаю предпочтение p += 1 вместо ++;
lol.gif
Шаманим потихоньку?

Стандарт С:
Цитата
6.5.3.1 Prefix increment and decrement operators
...
Semantics
2 The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation. The expression ++E is equivalent to (E+=1). See the discussions of additive operators and compound assignment for information on constraints, types, side effects, and conversions and the effects of operations on pointers.
3 The prefix -- operator is analogous to the prefix ++ operator, except that the value of the operand is decremented.

Цитата
6.5.16.2 Compound assignment
Semantics
3 A compound assignment of the form E1 op= E2 differs from the simple assignment expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once.


++E эквивалентно E+=1 всегда
любое из них эквивалентно E = E + 1 в подавляющем большинстве случаев.
Разница будет, например, для a[i] += 1; в случае, когда i объявлено как volatile, иначе выражения семантически эквивалентны.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 2 2008, 12:15
Сообщение #49


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(ReAl @ Apr 2 2008, 13:55) *
lol.gif
Шаманим потихоньку?
++E эквивалентно E+=1 всегда

Это я в курсе smile.gif
Дело принципа и привычки, от ++ в глазах рябит. Как и написал выше ++/-- использую только для индексации и в условиях:

while( zz--)
{
*p++ = xx;
p[ idx++] = xx;
}
...

а когда стоит вопрос одинокого инкремента какой-то переменной или указателя то пользую

p += 1;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 2 2008, 12:34
Сообщение #50


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(defunct @ Apr 2 2008, 12:58) *
Просто кому придет в голову объявить переменную ОДНОЙ ЗАГЛАВНОЙ буквой?
Ну как же? локальную переменную типа char для цикла в puts так и хочется обозвать заглавной C.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 2 2008, 12:39
Сообщение #51


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Сергей Борщ @ Apr 2 2008, 14:34) *
Ну как же? локальную переменную типа char для цикла в puts так и хочется обозвать заглавной C.

кому как, во всех реализациях, что я встечал параметр put'ов описан прописной "c" или (чаще) "ch".
и лок. переменную почему бы не назвать одним из этих имен. ;>
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 2 2008, 12:40
Сообщение #52


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(defunct @ Apr 2 2008, 14:15) *
Это я в курсе smile.gif
Дело принципа и привычки, от ++ в глазах рябит.
Фух, а то я уж, виноват, подумал, что это способ уменьшения размера глюкодрома по причине врождённой глюкавости операторов ++ --.
Привычки - это нормально, ненормально когда их оправдывают высокими соображениями smile.gif


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 2 2008, 12:43
Сообщение #53


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(ReAl @ Apr 2 2008, 14:40) *
Фух, а то я уж, виноват, подумал, что это способ уменьшения размера глюкодрома по причине врождённой глюкавости операторов ++ --.

Я виноват что смайлик забыл поставить после "ни ни" smile.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 2 2008, 15:01
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(ReAl @ Apr 2 2008, 14:55) *
По поводу смешанных проектов - никто не мешает весь С-текст держать в отдельных файлах, компилировать в С-режиме со всеми функциональными макросами, а потом линковать с С++ - программой, скомпилированной в С++ режиме.

Да? А как вызывать "С++" функции из "С"? Через псевдосишные сишные обертки? - нет спасибо..


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 2 2008, 16:40
Сообщение #55


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Позволю небольшой отрывок кода, извиняюсь что немного прерываю...
доступ к флагам
Код
/****************************************************************************
Системные флаги
****************************************************************************/
#define System_Flags GPIOR0
enum
    {
        KEY_VALID     = (1 << 0),
        NEED_FLASH    = (1 << 1),
        SOUND_ENABLE  = (1 << 2)
    };

void  main (void){
  if(System_Flags & KEY_VALID) System_Flags &= ~NEED_FLASH;
  if(System_Flags & NEED_FLASH) System_Flags &= ~SOUND_ENABLE;
};

тот же код но с препроцессором
Код
#define System_Flags GPIOR0
#define KEY_VALID  (1 << 0)
#define NEED_FLASH  (1 << 1)
#define SOUND_ENABLE (1 << 2)
void  main (void){
  if(System_Flags & KEY_VALID) System_Flags &= ~NEED_FLASH;
  if(System_Flags & NEED_FLASH) System_Flags &= ~SOUND_ENABLE;
};

Даёт одинаковый код smile.gif
Код
//   18   if(System_Flags & KEY_VALID) System_Flags &= ~NEED_FLASH;
        SBIC    0x1E, 0x00
        CBI     0x1E, 0x01
//   19   if(System_Flags & NEED_FLASH) System_Flags &= ~SOUND_ENABLE;
??main_0:
        SBIC    0x1E, 0x01
        CBI     0x1E, 0x02


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 2 2008, 18:34
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Вот об этом я и говорю - богатство выбора в рамках языка.

При написании сложных операторов с большим количеством операций по типу ++/-- могут быть грабли. Они достаточно подробно описаны даже в учебниках. Но, как мне кажется, не стоит перегружать операторы. Это неудобно для отладки к примеру и ухудшает читаемость. С другой стороны, совершенно очевидно, что компилятору по барабану написали ли вы формулу одним оператором или тремя. Качество сгенерированного кода не ухудшится
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Apr 2 2008, 18:53
Сообщение #57


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(ReAl @ Apr 2 2008, 15:40) *
...способ уменьшения размера глюкодрома по причине врождённой глюкавости операторов ++ --.
Привычки - это нормально, ненормально когда их оправдывают высокими соображениями smile.gif


Есть совершенно нормальный предел восприятия кракозябров, ибо ни Вы, ни я не начинали учить буквы с "Hello, world!" Т.е. чистая психология восприятия. Поэтому, когда мне закинут в уши мысль типа : " зато на Паскале написана масса давно и надежно работающих программ для NASA" - я поверю. Потому что в Паскале нет возможности извратить язык и сделать нечто подобное тому, что описано в первых постах.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Apr 2 2008, 19:19
Сообщение #58


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SasaVitebsk @ Apr 2 2008, 22:34) *
С другой стороны, совершенно очевидно, что компилятору по барабану написали ли вы формулу одним оператором или тремя. Качество сгенерированного кода не ухудшится

Более того, при написании 3мя операторами оно может и существенно улучшиться 07.gif
если знаешь как правильно разбить эти 3 оператора на нужное количество строк...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 2 2008, 19:30
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(SasaVitebsk @ Apr 2 2008, 21:34) *
... совершенно очевидно, что компилятору по барабану написали ли вы формулу одним оператором или тремя. Качество сгенерированного кода не ухудшится

Компиляторы умнеют, но тем не менее пока не умнее Вас и на подсказку вполне вероятно, ответят лучшим кодом.


Цитата(singlskv @ Apr 2 2008, 22:19) *
Более того, при написании 3мя операторами оно может и существенно улучшиться 07.gif
если знаешь как правильно разбить эти 3 оператора на нужное количество строк...

Вы знаете? Тогда пример в студию......

Цитата(_Pasha @ Apr 2 2008, 21:53) *
Поэтому, когда мне закинут в уши мысль типа...

smile.gif ну зачем-же гордится своей наивностью?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 2 2008, 19:53
Сообщение #60


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Хотя я в NASA не работал, но по слухам там не применялся Pascal. Вроде бы Modula или что-то подобное. Знаю точно, что чисто объектно ориентированный язык. И именно из соображений безопасности и защищённости. На данный момент, вроде проскакивали сообщения, что принято решение о применении C++ в качестве базового языка.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Apr 2 2008, 20:31
Сообщение #61


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(zltigo @ Apr 2 2008, 23:30) *
Вы знаете? Тогда пример в студию......
Да пожалуйста, WinAvr20060421, на IAR тоже как-то проверял, чуть получше но тоже не блеск:
Код
#include <avr/io.h>

volatile unsigned char al=0xFF;
volatile unsigned char ah=0xFF;
volatile unsigned char Pb,Pc,Pd;

int main()
{
  unsigned char pb,pc,pd;

  unsigned char tmpl = al;
  unsigned char tmph = ah;

//------------ Вариант N1 ("правильный")
  pb = (tmph & 0b10000000) | ((tmph & 0b01110000) >> 1) | ((tmph & 0b00001100) >> 2);
  pc = ((tmph & 0b00000011) << 2) | ((tmpl & 0b11000000) >> 6);
  pd = tmpl <<2;
//----- сохраняем результат
  Pb = pb;
  Pc = pc;
  Pd = pd;


  tmpl = al;
  tmph = ah;

//------------ Вариант N2 ("неправильный :) ")
  pd = (tmpl << 2);
  pc = tmph & 0b01111100;
  pc >>= 1;
  pb = (tmph & 0b10000000);
  pb |= (pc & 0b00111000);
  pc &= 0b00000110;
  pc >>= 1;
  pb |= pc;
  pc = (tmph&0b00000011);
  pc <<= 2;
  pd = tmpl >> 6;
  pc |= pd;
  pd = tmpl << 2;
//----- сохраняем результат
  Pb = pb;
  Pc = pc;
  Pd = pd;

//---------------------------

  while (1);

}

результат компиляции:
Код
pb = (tmph & 0b10000000) | ((tmph & 0b01110000) >> 1) | ((tmph & 0b00001100) >> 2);
  6c:    24 2f           mov    r18, r20
  6e:    33 27           eor    r19, r19
  70:    c9 01           movw    r24, r18
  72:    80 77           andi    r24, 0x70; 112
  74:    90 70           andi    r25, 0x00; 0
  76:    95 95           asr    r25
  78:    87 95           ror    r24
  7a:    40 78           andi    r20, 0x80; 128
  7c:    48 2b           or    r20, r24
  7e:    c9 01           movw    r24, r18
  80:    8c 70           andi    r24, 0x0C; 12
  82:    90 70           andi    r25, 0x00; 0
  84:    95 95           asr    r25
  86:    87 95           ror    r24
  88:    95 95           asr    r25
  8a:    87 95           ror    r24
  8c:    48 2b           or    r20, r24
  pc = ((tmph & 0b00000011) << 2) | ((tmpl & 0b11000000) >> 6);
  8e:    23 70           andi    r18, 0x03; 3
  90:    30 70           andi    r19, 0x00; 0
  92:    22 0f           add    r18, r18
  94:    33 1f           adc    r19, r19
  96:    22 0f           add    r18, r18
  98:    33 1f           adc    r19, r19
  9a:    85 2f           mov    r24, r21
  9c:    99 27           eor    r25, r25
  9e:    36 e0           ldi    r19, 0x06; 6
  a0:    96 95           lsr    r25
  a2:    87 95           ror    r24
  a4:    3a 95           dec    r19
  a6:    e1 f7           brne    .-8      ; 0xa0 <main+0x44>
  a8:    28 2b           or    r18, r24
  pd = tmpl <<2;
  aa:    55 0f           add    r21, r21
  ac:    55 0f           add    r21, r21

Код
  pd = (tmpl << 2);
  pc = tmph & 0b01111100;
  c2:    24 2f           mov    r18, r20
  c4:    2c 77           andi    r18, 0x7C; 124
  pc >>= 1;
  c6:    26 95           lsr    r18
  pb = (tmph & 0b10000000);
  c8:    94 2f           mov    r25, r20
  ca:    90 78           andi    r25, 0x80; 128
  pb |= (pc & 0b00111000);
  cc:    82 2f           mov    r24, r18
  ce:    88 73           andi    r24, 0x38; 56
  d0:    98 2b           or    r25, r24
  pc &= 0b00000110;
  d2:    26 70           andi    r18, 0x06; 6
  pc >>= 1;
  d4:    26 95           lsr    r18
  pb |= pc;
  d6:    92 2b           or    r25, r18
  pc = (tmph&0b00000011);
  d8:    24 2f           mov    r18, r20
  da:    23 70           andi    r18, 0x03; 3
  pc <<= 2;
  dc:    22 0f           add    r18, r18
  de:    22 0f           add    r18, r18
  pd = tmpl >> 6;
  e0:    85 2f           mov    r24, r21
  e2:    82 95           swap    r24
  e4:    86 95           lsr    r24
  e6:    86 95           lsr    r24
  e8:    83 70           andi    r24, 0x03; 3
  pc |= pd;
  ea:    28 2b           or    r18, r24
  pd = tmpl << 2;
  ec:    55 0f           add    r21, r21
  ee:    55 0f           add    r21, r21


ИТОГО:
"Правильный" 21 слов 58 тактов
"Неправильный" 17 слов 23 такта

Выводы делаем сами 07.gif
Go to the top of the page
 
+Quote Post
AlexKLm
сообщение Apr 2 2008, 21:22
Сообщение #62


Частый гость
**

Группа: Свой
Сообщений: 160
Регистрация: 17-03-08
Из: Мурманская
Пользователь №: 35 989



На СИ, правильно когда по-больше зелени (#define), а на C++, а тем более шарпе, - когда этого по-меньше. Шучу. Важно чтобы программа работала, менее важно - как она написана. Если расчитывать что кому-то придется в этом коде разбираться, то желательно писать коментарии. Даже самому приходится иногда разбирая старый код вспоминать что же там имелось ввиду. Мне нравится стиль Microsoft, лучше трудно придумать.


--------------------
Демократия - это когда считается, что два дурака лучше одного умного
Суверенная демократия - это когда считается, что один дурак лучше двух дураков
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 2 2008, 21:51
Сообщение #63


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(singlskv @ Apr 2 2008, 23:31) *
Да пожалуйста, WinAvr20060421, на IAR тоже как-то проверял, чуть получше но тоже не блеск:

Ну и где обещанная экономия от
Цитата
...правильно разбить эти 3 оператора на нужное количество строк...

Налицо ДВА РАЗНЫХ АЛГОРИТМА, а не описание одного и того-же "разным количеством строк".
Кроме того, посмею предположить, что под нормально оптимизирующим компилятором разница будет в пару команд максимум.
Цитата
Выводы делаем сами

Сделал smile.gif



Цитата(AlexKLm @ Apr 3 2008, 00:22) *
Мне нравится стиль Microsoft, лучше трудно придумать.

Трудно придумать стиль в котором больше жертв принесено стилю ради собственно абсолютно формального стиля.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
singlskv
сообщение Apr 2 2008, 21:55
Сообщение #64


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(zltigo @ Apr 3 2008, 01:47) *
Налицо ДВА РАЗНЫХ АЛГОРИТМА,
с ОДИНАКОВЫМ результатом, и принципиально не различающимся методом вычислений,
+ если Вы не обратили внимание, во втором варианте операции на одну больше smile.gif
Цитата
Кроме того, посмею предположить, что под нормально оптимизирующим компилятором разница будет в пару команд максимум.
покажите результат компиляции...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 2 2008, 22:08
Сообщение #65


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(singlskv @ Apr 3 2008, 00:55) *
покажите результат компиляции...

А самому? Думаете поленюсь copy-paste и убрать отрыжки древних ассемблеров не имеющих препроцессоров? Ладно:
Код
//   19 void m1(void)
m1:
//   20 {
//   21 unsigned char pb,pc,pd;
//   22
//   23 unsigned char tmpl = al;
        LDI     R30, LOW(al)
        LDI     R31, (al) >> 8
        LD      R19, Z
//   24 unsigned char tmph = ah;
        LDD     R16, Z+1
//   25
//   26 //------------ Вариант N1 ("правильный")
//   27   pb = ( tmph & 0x80 )|( (tmph & 0x70) >> 1 )|( (tmph & 0xC0) >> 2 );
//   28   pc = ((tmph & 0x03) << 2 )|( (tmpl & 0xC0) >> 6 );
//   29   pd = tmpl <<2;
//   30
//   31 //----- сохраняем результат
//   32   Pb = pb;
        MOV     R18, R16
        ANDI    R18, 0x80
        MOV     R17, R16
        ANDI    R17, 0x70
        ASR     R17
        OR      R18, R17
        MOV     R17, R16
        ANDI    R17, 0xC0
        LSR     R17
        LSR     R17
        OR      R18, R17
        STD     Z+2, R18
//   33   Pc = pc;
        ANDI    R16, 0x03
        LSL     R16
        LSL     R16
        LDI     R17, 4
        MUL     R19, R17
        OR      R16, R1
        STD     Z+3, R16
//   34   Pd = pd;
        LSL     R19
        LSL     R19
        STD     Z+4, R19
//   35
//   36 }
        RET



//   38 void m2(void)
m2:
//   39 {
//   40
//   41 unsigned char pb,pc,pd;
//   42
//   43 unsigned char tmpl = al;
        LDI     R30, LOW(al)
        LDI     R31, (al) >> 8
        LD      R20, Z
//   44 unsigned char tmph = ah;
        LDD     R18, Z+1
//   45
//   46 //------------ Вариант N2 ("неправильный :) ")
//   47       pd = (tmpl << 2);
//   48
//   49     pc = tmph & 0x7C;
//   50       pc >>= 1;
        MOV     R17, R18
        ANDI    R17, 0x7C
        LSR     R17
//   51
//   52     pb = (tmph & 0x80);
//   53       pb |= (pc & 0x38);
//   54       pc &= 0x06;
//   55       pc >>= 1;
//   56       pb |= pc;
//   57       pc = tmph & 0x03;
//   58       pc <<= 2;
//   59       pd = tmpl >> 6;
//   60       pc |= pd;
//   61       pd = tmpl << 2;
//   62 //----- сохраняем результат
//   63   Pb = pb;
        MOV     R19, R18
        ANDI    R19, 0x80
        MOV     R16, R17
        ANDI    R16, 0x38
        OR      R19, R16
        ANDI    R17, 0x06
        LSR     R17
        OR      R19, R17
        STD     Z+2, R19
//   64   Pc = pc;
        ANDI    R18, 0x03
        LSL     R18
        LSL     R18
        LDI     R16, 4
        MUL     R20, R16
        OR      R18, R1
        STD     Z+3, R18
//   65   Pd = pd;
        LSL     R20
        LSL     R20
        STD     Z+4, R20
//   66 }
        RET

P.S.
Получилось, что все ухищрения яйца выеденного не стоят....


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 2 2008, 22:32
Сообщение #66


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(singlskv @ Apr 2 2008, 23:55) *
с ОДИНАКОВЫМ результатом, и принципиально не различающимся методом вычислений,
Но тем не менее разных алгоритма :-)
Кстати, если переписать это так, как привычно мне wink.gif - сначала сдвиги, потом маскирования (так как сдвиги С часто компилируются в ассемблерные сдвиги с последующим маскированием, маскирования, разделённые сдвигом, часто остаются, хотя они и ихбыточные, а вот два маскирования подряд компиляторы как правило объединяют smile.gif ), да и мне лично проще анализировать "сначала сдвиг, потом маскирование"
Код
__asm__ volatile ("nop" ::); // так удобнее искать потом границы фрагментов

  tmpl = al;
  tmph = ah;

  pb = (tmph & 0b10000000) | ((tmph >> 1) & 0b00111000) | ((tmph >> 2) & 0b00000011);
  pc = ((tmph << 2) & 0b00001100) | ((tmpl >> 6) & 0b00000011);
  pd = tmpl <<2;
//-----
  Pb = pb;
  Pc = pc;
  Pd = pd;
__asm__ volatile ("nop" ::);
то особой разницы-то и под gcc не видно...

Код
/* #APP */
    nop
/* #NOAPP */
    lds r19,al
    lds r25,ah
    mov r18,r25
    lsr r18
    andi r18,lo8(56)
    mov r24,r25
    lsr r24
    lsr r24
    andi r24,lo8(3)
    or r18,r24
    mov r24,r25
    andi r24,lo8(-128)
    or r18,r24
    lsl r25
    lsl r25
    andi r25,lo8(12)
    mov r24,r19
    swap r24
    lsr r24
    lsr r24
    andi r24,lo8(3)
    or r25,r24
    lsl r19
    lsl r19
    sts Pb,r18
    sts Pc,r25
    sts Pd,r19
/* #APP */
    nop
/* #NOAPP */
    lds r20,al
    lds r25,ah
    mov r24,r25
    andi r24,lo8(124)
    lsr r24
    mov r19,r24
    andi r19,lo8(56)
    mov r18,r25
    andi r18,lo8(-128)
    or r19,r18
    andi r24,lo8(6)
    lsr r24
    or r19,r24
    andi r25,lo8(3)
    lsl r25
    lsl r25
    mov r24,r20
    swap r24
    lsr r24
    lsr r24
    andi r24,lo8(3)
    or r25,r24
    sts Pb,r19
    sts Pc,r25
    lsl r20
    lsl r20
    sts Pd,r20
.L2:
    rjmp .L2


Цитата(zltigo @ Apr 2 2008, 23:51) *
Трудно придумать стиль в котором больше жертв принесено стилю ради собственно абсолютно формального стиля.
+1
У меня мозги в трубочку сворачиваются и через уши вылазят, когда я вижу идентификаторы в стиле
ВЗБЗД взбздНуть;
Их трудно произнести и, как следствие, ими трудно мыслить. Зато вылет за правый край экрана даже при отступах по 2 символа (о ужас дельфийский) гарантирован даже на операторах средней сложности.
Итого народ пишет исключительно простые, но софт от этого ни компактнее, ни лучше не становится. Как, впрочем, не становится лучше и обычный текст, не содержащий совершенно сложноподчинённых предложений, а состоящий из одних простых ("зато нет глюкодрома с запятыми" smile.gif ).


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
singlskv
сообщение Apr 2 2008, 22:37
Сообщение #67


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(zltigo @ Apr 3 2008, 02:08) *
и убрать отрыжки древних ассемблеров не имеющих препроцессоров?
это не отрыжки, это удобство для данной конкретной задачки,
по битикам видно что куда попадает, но это просто специфика...
Кстати Вы вот так и ошиблись при переводе из двоичного представления в 16x
вот так:
(tmph & 0b10000000)......(tmph & 0b01110000).......(tmph & 0b00001100 )
сразу же видно что взяли нужные битики,
а вот так нифига не видно:
( tmph & 0x80 )........(tmph & 0x70)..........(tmph & 0xC0 )

Цитата
А самому?
Код
........
Я же говорю, пробовал, раньше код был намного хуже.
Какая версия ?
С таким выходом - убедили!
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 2 2008, 22:46
Сообщение #68


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(singlskv @ Apr 3 2008, 00:37) *
Я же говорю, пробовал, раньше код был намного хуже.
Какая версия ?
Мой вариант - 20071221, но и на 20060421 полный паритет между вариантами "мой самый правильный" wink.gif и "неправильный"
Код
/* #APP */
    nop
/* #NOAPP */
    lds r21,al
    lds r20,ah
    mov r25,r20
    andi r25,lo8(-128)
    mov r24,r20
    lsr r24
    andi r24,lo8(56)
    or r25,r24
    mov r24,r20
    lsr r24
    lsr r24
    andi r24,lo8(3)
    or r25,r24
    lsl r20
    lsl r20
    andi r20,lo8(12)
    mov r24,r21
    swap r24
    lsr r24
    lsr r24
    andi r24,0x3
    or r20,r24
    lsl r21
    lsl r21
    sts Pb,r25
    sts Pc,r20
    sts Pd,r21
/* #APP */
    nop
/* #NOAPP */
    lds r21,al
    lds r20,ah
    mov r18,r20
    andi r18,lo8(124)
    lsr r18
    mov r25,r20
    andi r25,lo8(-128)
    mov r24,r18
    andi r24,lo8(56)
    or r25,r24
    andi r18,lo8(6)
    lsr r18
    or r25,r18
    mov r18,r20
    andi r18,lo8(3)
    lsl r18
    lsl r18
    mov r24,r21
    swap r24
    lsr r24
    lsr r24
    andi r24,0x3
    or r18,r24
    lsl r21
    lsl r21
    sts Pb,r25
    sts Pc,r18
    sts Pd,r21
.L2:
    rjmp .L2


У меня на компе и 20060421 до сих пор стоит, на всякий случай.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
singlskv
сообщение Apr 2 2008, 23:25
Сообщение #69


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(ReAl @ Apr 3 2008, 02:32) *
Кстати, если переписать это так, как привычно мне wink.gif - сначала сдвиги, потом маскирования (так как сдвиги С часто компилируются в ассемблерные сдвиги с последующим маскированием, маскирования, разделённые сдвигом, часто остаются, хотя они и ихбыточные, а вот два маскирования подряд компиляторы как правило объединяют smile.gif ), да и мне лично проще анализировать "сначала сдвиг, потом маскирование"
Так собственно мы и сделали одно и тоже но разными средствами
Цитата(ReAl @ Apr 3 2008, 02:46) *
Мой вариант - 20071221, но и на 20060421 полный паритет между вариантами "мой самый правильный" wink.gif и "неправильный"
Мне просто почему-то удобнее мыслить сначала маскированием а потом сдвигами,
а 20060421 ну никак не хотел ко мне привыкать smile.gif


Цитата(ReAl @ Apr 3 2008, 02:46) *
У меня на компе и 20060421 до сих пор стоит, на всякий случай.
OFF: Кстати, может быть у Вас есть ответ на вот этот вопрос:
http://electronix.ru/forum/index.php?showtopic=26519
Никто так ничего толком и не ответил,
пару раз неприятно натыкался,
кроме как ручной тасовкой команд решения не знаю...
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 2 2008, 23:45
Сообщение #70


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(singlskv @ Apr 3 2008, 00:55) *
Так собственно мы и сделали одно и тоже но разными средствами
Так я и не говорю, что сделано что-то совсем другое (в отличие от варианта в 10 строк), просто неболшое переупорядочивание операций под мою голову smile.gif

Цитата(singlskv @ Apr 3 2008, 00:55) *
Мне просто почему-то удобнее мыслить сначала маскированием а потом сдвигами,
Если выделяется какое-то битовое поле в "целочисленную переменную", то "сначала сдвиг" показывает, где поле начиналось, а "потом маскирование" это просто число единичек справа, равное длине поля, т.е.
Код
fld = (var >> field_start) & ((1 << field_len) - 1);

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

Кстати, господа хорошие, что-то мне кажется, что этот вариант:
Код
  unsigned char tmph = ah;
  unsigned int tmp = (tmph<<8) | al;
  tmp <<= 2;
  
  pb = tmph & 0b10000000;
  tmph >>= 1;
  pb  |= tmph & 0b00111000;
  tmph >>= 1;
  pb |= tmph & 0b00000011;
  
//-----
  Pb = pb;
  Pc = (tmp>>8) & 0x0F;
  Pd = tmp;
Самый понятный с точки зрения "а что, собственно, делается".
И даже несмотря на традиционно плохонькую реализацию в gcc склеивания слова из двух байтов и выделения старшего байта слова (после оптимизатора остаются рудименты "integer promotion") - он находится "где-то там же" по длине.
Код
    lds r20,ah
    lds r24,al
    mov r18,r20; во аж сколько заняло
    ldi r19,lo8(0);   unsigned int tmp = (tmph<<8) | al;
    mov r19,r18;
    clr r18;
    ldi r25,lo8(0);
    or r18,r24;
    or r19,r25;
    lsl r18
    rol r19
    lsl r18
    rol r19
    mov r24,r20
    lsr r24
    mov r25,r24
    andi r25,lo8(56)
    andi r20,lo8(-128)
    or r25,r20
    lsr r24
    andi r24,lo8(3)
    or r25,r24
    sts Pb,r25
    mov r24,r19; а это недочищенный хвосты
    clr r25;  (tmp>>8) & 0x0F;
    andi r24,lo8(15)
    sts Pc,r24
    sts Pd,r18
Если бы оптимизатор был тут немного умнее, или если применить макрос-вставку
Код
#define HILOTO16(hi, lo) ({ \
    unsigned int __result; \
    __asm__ ( " mov %B0,%1 \n" : "=r" (__result) : "r" (hi), "0" (lo) ); \
    __result; })
...
...
  tmph = ah;
  unsigned int tmp = HILOTO16(tmph, al);
  tmp <<= 2;
  
  pb = tmph & 0b10000000;
  tmph >>= 1;
  pb  |= tmph & 0b00111000;
  tmph >>= 1;
  pb |= tmph & 0b00000011;
  
//-----
  Pb = pb;
  Pc = (tmp>>8) & 0x0F;
  Pd = tmp;


То по сравнению с "неправильным", казалось бы "уоптимизированным вусмерть" и практически непонятным вариантом выходит гораздо короче:
Код
    lds r25,ah
    lds r18,al  ;
/* #APP */
     mov r19,r25; это то, что вышло из макроса HILOTO16(),
/* #NOAPP */; правильный оптимизатор должен был бы сделать так же.
    lsl r18
    rol r19
    lsl r18
    rol r19
    mov r24,r25
    lsr r24
    mov r20,r24
    andi r20,lo8(56)
    andi r25,lo8(-128)
    or r20,r25
    lsr r24
    andi r24,lo8(3)
    or r20,r24
    sts Pb,r20
    mov r24,r19; это уж ладно
    clr r25;
    andi r24,lo8(15)
    sts Pc,r24
    sts Pd,r18



Цитата(singlskv @ Apr 3 2008, 01:25) *
OFF: Кстати, может быть у Вас есть ответ на вот этот вопрос:
http://electronix.ru/forum/index.php?showtopic=26519
Никто так ничего толком и не ответил,
пару раз неприятно натыкался,
кроме как ручной тасовкой команд решения не знаю...
Ответ таков - если это жутко критичное по скорости место - вписать ассемблерную вставку и забыть. Иначе - забить. Ну хуже оптимизаторы, чем они в принципе могут быть, хуже. Если постоянно копаться в выдаче компилятора и страдать от недооптимизации - то лучше перейти на асм.

Кстати, в большинстве случаев -Os для AVR даёт лучше код, чем -O2 :-)


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 3 2008, 05:53
Сообщение #71


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(singlskv @ Apr 3 2008, 01:37) *
это не отрыжки, это удобство для данной конкретной задачки,
по битикам видно что куда попадает, но это просто специфика...

Да ничего не видно, при "видно" не ошибся-бы,даже в 2 часа ночи...
А тут даже на 8bit глазоломка, а уж на 32 smile.gif
Цитата
сразу же видно что взяли нужные битики,

Более-менее видно когда такое написано,хоть на ASM, хоть на C, как минимум так:
Код
( tmph & BIT7 )........(tmph & (BIT6|BIT5|BIT4))..........

а вобще надо давать осмысленные имена
Код
( tmph & B_SIGN )........(tmph & M_LEVEL)..........

Цитата
Я же говорю, пробовал, раньше код был намного хуже.
Какая версия ?

IAR 5.10, но, полагаю, и на 4.x будет тот-же результат.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 3 2008, 07:23
Сообщение #72


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Вот я и говорю, что результат практически тот же при оптимизации, а при отладке неудобно большие громоздкие формулы (в приведенных примерах вполне нормальные). Поэтому здоровую формулу, с возможностью неоднозначного вычисления (точнее требующую специального разбора порядка вычисления), лучше разбить на пару однозначных. Компилятору всё равно, а человеку удобнее.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 3 2008, 08:28
Сообщение #73


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(SasaVitebsk @ Apr 3 2008, 09:23) *
Вот я и говорю, что результат практически тот же при оптимизации, а при отладке неудобно большие громоздкие формулы (в приведенных примерах вполне нормальные). Поэтому здоровую формулу, с возможностью неоднозначного вычисления (точнее требующую специального разбора порядка вычисления), лучше разбить на пару однозначных. Компилятору всё равно, а человеку удобнее.
Я бы сказал, что как раз этому критерию приведенный пример не отвечает абсолютно. "неправильный" вариант гораздо труднее для понимания, и чем первый "правильный", и чем мой с 16-битной переменной. Микс из элементарных операций с разными переменными, который нужно много раз прочесть туда-назад, чтобы понять в чём дело.
Он выглядит скорее как "а вот я умнее компилятора и напишу на С, но как бы на асме (всё равно не имея всех асмовых возможностей, кстати) и оно будет компактнее и работать быстрее", а не как "в таком виде оно понятнее человеку".


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 3 2008, 10:22
Сообщение #74


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(ReAl @ Apr 3 2008, 01:45) *
Кстати, в большинстве случаев -Os для AVR даёт лучше код, чем -O2 :-)

в большинстве случаев == всегда.


Цитата(SasaVitebsk @ Apr 3 2008, 09:23) *
Поэтому здоровую формулу, с возможностью неоднозначного вычисления (точнее требующую специального разбора порядка вычисления), лучше разбить на пару однозначных. Компилятору всё равно, а человеку удобнее.

+1000
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Apr 3 2008, 12:57
Сообщение #75


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Кто о чем, а вшивый - о бане...
Пробегала книжка C style guide 1994.
Это про NASA smile.gif
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 7 2008, 10:40
Сообщение #76


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(zltigo @ Apr 2 2008, 22:30) *
Компиляторы умнеют, но тем не менее пока не умнее Вас и на подсказку вполне вероятно, ответят лучшим кодом.

К примеру с чем связано столько заморочек в ВИН АВР?
Макрос доступа к битам порта средствами ВИН АВР, например
sbi(PORTB, 5);
Подняв несколька файлов и сделав соответствующие подстановки получаем
следующее ( адрес порта Б к примеру 0x08)
Код
((*(volatile uint8_t *)(((uint16_t) &((*(volatile uint8_t *)((0x08) + 0x20)))) ))   |=(1 << (5)))

средствами ИАР это дело обстоит намного проще и находится в одном файле avr_macros.h
Код
/* Set BIT in ADDRESS */
#define SETBIT(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Apr 7 2008, 10:58
Сообщение #77


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
средствами ИАР это дело обстоит намного проще

А как насчёт то же применить в WinAVR? Неужели этот макрос там не будет работать? Вы хоть попробовать-то пытались?


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 7 2008, 11:07
Сообщение #78


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(sensor_ua @ Apr 7 2008, 13:58) *
А как насчёт то же применить в WinAVR? Неужели этот макрос там не будет работать? Вы хоть попробовать-то пытались?

Да, я немного не про то. Конечно он будет работать. Это и такому дураку как я понятно smile.gif

Попробуйте в ИАР вот так и объясните почему, а то мне дураку не ясно
Допустим нужно установить в единицу четвёртый бит порта ну пускай Б
Настроим его как выход, назовём его HELS
Код
#define HELSp B
#define HELSb 4
CLRDDR(HELS);// направление
SETPORT(HELS);// бит 4 порта Б единичка


Сообщение отредактировал sKWO - Apr 7 2008, 11:41


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Apr 7 2008, 12:51
Сообщение #79


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Не очень понял, что Вы хотите, но на телесистемах на днях обсуждался вариант доступа только по имени.
Код
typedef volatile uint8_t * port_t;

typedef struct Port_Bit{
  port_t Port;
  unsigned char Bit;
}Port_Bit;

void CLRDDR(const Port_Bit * pb){
  *(pb->Port-1) &= ~(1 << pb->Bit);
}
void SETPORT(const Port_Bit * pb){
  *(pb->Port) |= 1 << pb->Bit;
}

Port_Bit dHELS={&PORTB, 4};
const Port_Bit * HELS = &dHELS;


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 7 2008, 17:49
Сообщение #80


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



спасибо за инфу!!


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 7 2008, 19:43
Сообщение #81


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(sKWO @ Apr 7 2008, 13:40) *
К примеру с чем связано столько заморочек в ВИН АВР?
Макрос доступа к битам порта средствами ВИН АВР, например
sbi(PORTB, 5);
Подняв несколька файлов и сделав соответствующие подстановки получаем
следующее ( адрес порта Б к примеру 0x08)
Код
((*(volatile uint8_t *)(((uint16_t) &((*(volatile uint8_t *)((0x08) + 0x20)))) ))   |=(1 << (5)))
средствами ИАР это дело обстоит намного проще и находится в одном файле avr_macros.h
Код
/* Set BIT in ADDRESS */
#define SETBIT(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
Средствами WinAVR это "всё" тоже было одной практически такой же строкой
Код
#define sbi(port, bit) (port) |= (1 << (bit))
Зачем её было раскручивать? Какая разница что там, если оно всё равно компилируется в одну такую же команду ассемблера, что и у IAR ?

Ведь для SETBIT(PORTB,5) вы же у IAR не раскручивали, что такое PORTB и не сравнивали с WinAVR?
А он выглядит так

WinAVR:
Код
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + 0x20)
...
#define PORTB    _SFR_IO8(0x18)
Кстати, что-то Ваш вариант раскрутки sbi(port,bit) длинноват, выходит короче
Код
( *(volatile uint8_t *)((0x08) + 0x20) )    |=(1 << (5))


IAR:
Код
#define __BYTEBITS(_NAME,_A,_B,_C,_D,_E,_F,_G,_H) \
unsigned char _NAME ## _ ## _A:1, \
              _NAME ## _ ## _B:1, \
              _NAME ## _ ## _C:1, \
              _NAME ## _ ## _D:1, \
              _NAME ## _ ## _E:1, \
              _NAME ## _ ## _F:1, \
              _NAME ## _ ## _G:1, \
              _NAME ## _ ## _H:1;

#define SFR_B_BITS(_NAME, _ADDR, _A,_B,_C,_D,_E,_F,_G,_H) \
    __io union { \
      unsigned char   _NAME;           /* The sfrb as 1 byte */ \
      struct {                        /* The sfrb as 8 bits */ \
        __BYTEBITS(_NAME, _A,_B,_C,_D,_E,_F,_G,_H) \
      };  \
    } @ _ADDR;

#define SFR_B(_NAME, _ADDR) SFR_B_BITS(_NAME, _ADDR, \
                                    Bit0,Bit1,Bit2,Bit3,Bit4,Bit5,Bit6,Bit7)
...

SFR_B(PORTB,  0x18)
Так что у IAR просто наворочено в другом месте, до которого просто Вы не добрались :-)
Как лучше - тяжело сказать. Вариант IAR позволяет написать
Код
SPMCR.SPMIE = 1;
вместо
Код
SPMCR |= (1 << SPMIE);
или
SPMCR |= _BV(SPMIE);

зато не позволяет сделать то, что позволяет avr-gcc
(к чему это приводит - см, например, http://electronix.ru/forum/index.php?s=&am...st&p=377042 )
Код
#if defined(SPMCSR)
#  define SPM_CONTROL_REG SPMCSR
#elif defined(SPMCR)
#  define SPM_CONTROL_REG SPMCR
#else
#  error "SPM control register not defined"
#endif

...

SPM_CONTROL_REG |= (1 << SPMIE);
Таким образом для всех кристаллов, у которых есть либо SPMCR либо SPMCSR - можно обойтись несколькими строками кода и получить исходник, компилирующийся для всего. У IAR для этого придётся персонально проверять типы процесоров через
Код
#if defined(__AT90Mega88__) || defined(__AT90Mega168__) || ...

А всё потому, что PORTB да SPMCR у avr-gcc это макросы препроцессора, а у IAR - переменные-вложенные агрегаты, прибитые гвозядми к адресам, поэтому их наличие или отсутствие препроцессор не видит и нельзя сделать условную компиляцию просто проверив наличие имени регистра.


Цитата(sKWO @ Apr 7 2008, 14:07) *
Допустим нужно установить в единицу четвёртый бит порта ну пускай Б
Настроим его как выход, назовём его HELS
Код
#define HELSp B
#define HELSb 4
CLRDDR(HELS);// направление
SETPORT(HELS);// бит 4 порта Б единичка
Это вообще уже лет 10 не так делается.

Код
#define LED1 B,0,L   /* светодиод анодом на питание, зажигаем низким уровнем - L */
#define LED2 D,1,H   /* светодиод катодом на землю, зажигаем высоким  уровнем */
#define KEY1 C,2,L  /* кнопка на землю, при нажатии низкий уровень */
#define KEY2 A,3,H /*  кнопка на питание, при нажатии высокий уровень */
...
  // теперь не глядя на полярности сигналов пишем ON, чтобы включить, а включается
  // нулём или единичкой - макрос разбирается
  DRIVER(LED1,OUT);
  DRIVER(LED2,OUT);
  DRIVER(KEY1,IN);
  DRIVER(KEY1,PULLUP); // к примеру тут обходимся внутренней подтяжкой
  DRIVER(KEY2,IN);
  DRIVER(KEY2,HIZ);   // а тут внешняя подтяжка на землю
...
  if( ACTIVE(KEY1) ) {
    ON(LED1);
    OFF(LED2);
  }

  if( ACTIVE(KEY2) ) OFF(LED1);

  if( flag) ) CPL(LED2); // проинвертировали ногу


Называется "макросы Аскольда Волкова", модифицировалось уже под разные процессоры и компиляторы всеми кому не лень. Вот мой вариант:
Прикрепленные файлы
Прикрепленный файл  pin_macros.zip ( 1.32 килобайт ) Кол-во скачиваний: 112
 


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 8 2008, 11:00
Сообщение #82


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(ReAl @ Apr 7 2008, 22:43) *
Называется "макросы Аскольда Волкова", модифицировалось уже под разные процессоры и компиляторы всеми кому не лень.

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

Цитата(ReAl @ Apr 7 2008, 22:43) *
А всё потому, что PORTB да SPMCR у avr-gcc это макросы препроцессора, а у IAR - переменные-вложенные агрегаты, прибитые гвозядми к адресам, поэтому их наличие или отсутствие препроцессор не видит и нельзя сделать условную компиляцию просто проверив наличие имени регистра.

За это большое спасибо!


Цитата(ReAl @ Apr 7 2008, 22:43) *
длинноват, выходит короче
Код
( *(volatile uint8_t *)((0x08) + 0x20) )    |=(1 << (5))

Код
в файле sfr_def.h находим
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
дальше
#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
дальше
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _SFR_ADDR(sfr) _SFR_MEM_ADDR(sfr)  
#define _SFR_MEM_ADDR(sfr) ((uint16_t) &(sfr))
получаем
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
подставляем
#define sbi(sfr, bit) (   (*(volatile uint8_t *)(   ((uint16_t) &(sfr))   ))   |= _BV(bit))
смотрим в  pgmspace.h  _BV
#define _BV(bit) (1 << (bit))
видим
#define sbi(sfr, bit)  ((*(volatile uint8_ t *)(((uint16_t) &(sfr)) ))   |=  (1 << (bit)))
всё хорошо получается или чёта провтыкал?
имеем следующее
((*(volatile uint8_t *)(((uint16_t) &(PORTB )) ))   |=  (1 << (5)))
ну и остаётся за малым подставить знач порта
допустим
#define PORTB  _SFR_IO8(0x08)
находим _SFR_IO8 в файле sfrdefs.h
#define _SFR_IO8(io_addr) _MMIO_BYTE ((io_addr) + 0x20)
соответственно _SFR_IO8(0x08) есть_MMIO_BYTE((0x08) + 0x20)
а  _MMIO_BYTE((0x08) + 0x20) есть (*(volatile uint8_t *)((0x08) + 0x20))
отсюда и получается
((*(volatile uint8_t *)(((uint16_t) &((*(volatile uint8_t *)((0x08) + 0x20)))) ))   |=(1 << (5)))

Выходит разные версии компилят , наверное smile.gif


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post

6 страниц V   1 2 3 > » 
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 22:31
Рейтинг@Mail.ru


Страница сгенерированна за 0.02748 секунд с 7
ELECTRONIX ©2004-2016