|
|
  |
вопросы по IAR, В поисках идеального компилятора |
|
|
|
Oct 27 2005, 08:58
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Перехожу на С, в связи с этим пересмотрел ICC CV и наконец добрался до IAR Для начала пересмотрел все что уже было сказано, много пока туманно надо будет осмысливать. Первый вопрос, хотя я вроде как с ответом утвердился, это возможно ли в IAR представить число в виде 0bxxxxxxxx. Лазая по настройкам пришел к выводу что нет такой возможности, да и в ANSI C это не предусмотрено. Или я чего-то не знаю ? Второй: вот в этой ветке http://forum.electronix.ru/index.php?showtopic=8829встретил описание макроса как Код #define _DDR_(a) DDR##a #define _DDR(a) _DDR##_(a) #define SETDDR(x) (_DDR(x##p)|=BIT(x##b)) //PORT A ********************************** #define OUT0p A #define OUT0b 4 SETDDR(OUT0); макрос который ставит 4 бит в DDRA В инклудах описаны только представления PORTA, DDRA, PINA, остальные как-то формируются ?? но как так и не понял.  В help на IAR по поводу ## нашел вот это: Rule 98 (required) There shall be at most one occurrence of the # or ## preprocessor operator in a single macro definition. How the rule is checked The compiler will generate an error, indicating a violation of this rule, if more than one of # or ## is used in combination. For example, the occurrence of # and ## in the same macro definition will trigger an error. Example of rule violations #define FOO(x) BAR(#x) ## _var Examples of correct code #define FOO(x) #x #define FOO(x) my_ ## x И опять ничего не понял  что за ## что он делает ? В книгах по С ничего такого не нашел... Кстати этот макрос работает на IAR и ICC, CV ругается. Может кто обьяснить что это за ## и как они работают ....
|
|
|
|
|
Oct 27 2005, 09:30
|

Участник

Группа: Новичок
Сообщений: 48
Регистрация: 6-05-05
Пользователь №: 4 784

|
## в макросе с параметром обозначает, что далее следует параметр макроса в символьном виде без разрывов, например: Код #define Stop(CHN) bCh##CHN##Up = 0; bCh##CHN = 0; Stop(13); // для препроцессора это "bCh13Up = 0; bCh13 = 0;"
--------------------
|
|
|
|
|
Oct 27 2005, 09:34
|

Профессионал
    
Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072

|
Цитата(&-rey @ Oct 27 2005, 11:58) Examples of correct code #define FOO(x) #x #define FOO(x) my_ ## x
Может кто обьяснить что это за ## и как они работают .... ## позволяет образовывать новые идентификаторы путем "склеивания" двух других идентификаторов. Например, объявление FOO(beep) препроцессор преобразует в my_beep. Подробности можно почитать здесь.
|
|
|
|
|
Oct 27 2005, 09:48
|

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

|
Цитата(&-rey @ Oct 27 2005, 11:58) Может кто обьяснить что это за ## и как они работают .... ## - это склейка аргументов после подстановки в одну лексему. В ранних версиях С не было, использовался комментарий. Препроцессор его выкидывал перед основной работой и само собой цепочки символов склеивались. Код // old C style: // #define GLUE2(a,b) a/**/b // ANSI #define GLUE2(a,b) a ## b
i = GLUE2(j + 2, 1); // всё равно что i = j + 21; # - это подстановка аргумента как текстовой строки Код #define DUMP(a) printf( "(" #a ") = %d\n", a)
int main(void) { int i=5, j=7; DUMP( sizeof( void * ) ); DUMP( i + j ); return 0; } или, что часто более полезно, так Код #define ENTRY(a) { a, #a } struct { int code; const char *name; } error_code_table[] = { ENTRY(ALL_OK), ENTRY(CRC_ERROR), ENTRY(BAD_COMMAND) }; что писать несколько веселее, чем Код ыtruct { int code; const char *name; } error_code_table[] = { { ALL_OK, "ALL_OK" }, { CRC_ERROR, "CRC_ERROR" }, { BAD_COMMAND, "BAD_COMMAND" } };
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 27 2005, 10:16
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Цитата(G}{OST @ Oct 27 2005, 12:30) ## в макросе с параметром обозначает, что далее следует параметр макроса в символьном виде без разрывов, например: Код #define Stop(CHN) bCh##CHN##Up = 0; bCh##CHN = 0; Stop(13); // для препроцессора это "bCh13Up = 0; bCh13 = 0;" То есть, если я правильно понял: ## (начало вставки) - параметр - ## (конец вставки) если до вставки ничего нет то можно не писать ## в начале и соответственно если после вставки ничего нет то можно ## не ставить Код #define SETDDR(x) (_DDR(x##p)|=BIT(x##b))
SETDDR(OUT0); будет выполняться так _DDR(OUTp)|=BIT(OUTb) а поскольку у нас #define OUT0p A #define OUT0b 4 то: _DDR(A)|=BIT(4) за счет #define _DDR(a) _DDR##_(a) будет подставлено: _DDR##_(A)|=BIT(4) и в итоге #define _DDR_(a) DDR##a преобразует все к виду: DDRA|=BIT(4) Вот только с последними двумя #define _DDR_(a) DDR##a #define _DDR(a) _DDR##_(a) не совсем понятно а именно Зачем #define _DDR(a) _DDR##_(a) почему не #define _DDR(a) DDR##a ???
|
|
|
|
|
Oct 27 2005, 10:18
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Цитата(halfdoom @ Oct 27 2005, 12:34) Цитата(&-rey @ Oct 27 2005, 11:58) Examples of correct code #define FOO(x) #x #define FOO(x) my_ ## x
Может кто обьяснить что это за ## и как они работают .... ## позволяет образовывать новые идентификаторы путем "склеивания" двух других идентификаторов. Например, объявление FOO(beep) препроцессор преобразует в my_beep. Подробности можно почитать здесь. Спасибо, счас буду переводить.
|
|
|
|
|
Oct 27 2005, 10:20
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Цитата(ReAl @ Oct 27 2005, 12:48) Цитата(&-rey @ Oct 27 2005, 11:58) Может кто обьяснить что это за ## и как они работают .... ## - это склейка аргументов после подстановки в одну лексему. В ранних версиях С не было, использовался комментарий. Препроцессор его выкидывал перед основной работой и само собой цепочки символов склеивались. Код // old C style: // #define GLUE2(a,b) a/**/b // ANSI #define GLUE2(a,b) a ## b
i = GLUE2(j + 2, 1); // всё равно что i = j + 21; # - это подстановка аргумента как текстовой строки Код #define DUMP(a) printf( "(" #a ") = %d\n", a)
int main(void) { int i=5, j=7; DUMP( sizeof( void * ) ); DUMP( i + j ); return 0; } или, что часто более полезно, так Код #define ENTRY(a) { a, #a } struct { int code; const char *name; } error_code_table[] = { ENTRY(ALL_OK), ENTRY(CRC_ERROR), ENTRY(BAD_COMMAND) }; что писать несколько веселее, чем Код ыtruct { int code; const char *name; } error_code_table[] = { { ALL_OK, "ALL_OK" }, { CRC_ERROR, "CRC_ERROR" }, { BAD_COMMAND, "BAD_COMMAND" } }; Спасибо, буду переваривать. А по поводу bin формата я прав, или что-то где-то недопонял?
|
|
|
|
|
Oct 27 2005, 10:35
|

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

|
Цитата(&-rey @ Oct 27 2005, 13:16) То есть, если я правильно понял: ## (начало вставки) - параметр - ## (конец вставки) если до вставки ничего нет то можно не писать ## в начале и соответственно если после вставки ничего нет то можно ## не ставить Нет, ## - это "двуместный оператор", он склеивает свои левый и правый аргументы (как "+" их складывает). Цитата(&-rey) А по поводу bin формата я прав, или что-то где-то недопонял? А что с bin-форматом? Я что-то не нашёл вопрос.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 27 2005, 10:43
|

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

|
Ещё для переваривания :-) Для неокрепших желудков - осторожно, понемногу :-) Вопрос вкусовой, но я не люблю писать лишнее, поэтому не стесняюсь писать так: Цитата(dlportio_driver.h) #ifndef DLPORTIO_DRIVER_H #define DLPORTIO_DRIVER_H
typedef WINAPI void (*DlPortWritePortUchar_t) (unsigned port, uint8_t data); typedef WINAPI uint8_t(*DlPortReadPortUchar_t) (unsigned p); typedef WINAPI void (*DlPortWritePortBufferUchar_t) (unsigned p, uint8_t * buf, int len); typedef WINAPI void (*DlPortReadPortBufferUchar_t) (unsigned p, uint8_t * buf, int len); typedef WINAPI void (*DlPortWritePortUshort_t) (unsigned p, uint16_t data); typedef WINAPI uint16_t(*DlPortReadPortUshort_t) (unsigned p); typedef WINAPI void (*DlPortWritePortBufferUshort_t) (unsigned p, uint16_t * buf, int len); typedef WINAPI void (*DlPortReadPortBufferUshort_t) (unsigned p, uint16_t * buf, int len);
class dlportio_driver : public port_io_driver { public: static dlportio_driver *create();
/* ЛИШНЕЕ ПОСКИПАНО */
protected: HINSTANCE hdlportio;
#define _DL_PTR(_f_) _f_##_t _f_##_P
_DL_PTR( DlPortWritePortUchar ); _DL_PTR( DlPortReadPortUchar ); _DL_PTR( DlPortWritePortBufferUchar ); _DL_PTR( DlPortReadPortBufferUchar ); _DL_PTR( DlPortWritePortUshort ); _DL_PTR( DlPortReadPortUshort ); _DL_PTR( DlPortWritePortBufferUshort ); _DL_PTR( DlPortReadPortBufferUshort );
#undef _DL_PTR
}; и в соответствующем исходнике Цитата(dlportio_driver.cpp) dlportio_driver *dlportio_driver::create() { #define _DL_LOAD(_f_) \ do {\ pdl->_f_##_P = (_f_##_t)GetProcAddress(pdl->hdlportio, #_f_);\ if(pdl->_f_##_P == NULL) {\ delete pdl;\ return NULL;\ }\ } while(0)
dlportio_driver *pdl = new dlportio_driver;
pdl->hdlportio = LoadLibrary("DLportIO.dll"); if (pdl->hdlportio == NULL) { delete pdl; // "Can't load port library\n" return NULL; }
_DL_LOAD( DlPortWritePortUchar ); _DL_LOAD( DlPortReadPortUchar ); _DL_LOAD( DlPortWritePortBufferUchar ); _DL_LOAD( DlPortReadPortBufferUchar ); _DL_LOAD( DlPortWritePortUshort ); _DL_LOAD( DlPortReadPortUshort ); _DL_LOAD( DlPortWritePortBufferUshort ); _DL_LOAD( DlPortReadPortBufferUshort );
return pdl;
#undef _DL_LOAD }
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 27 2005, 12:04
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Цитата(ReAl @ Oct 27 2005, 13:43) Ещё для переваривания :-) Для неокрепших желудков - осторожно, понемногу :-) Вопрос вкусовой, но я не люблю писать лишнее, поэтому не стесняюсь писать так: Цитата(dlportio_driver.h) #ifndef DLPORTIO_DRIVER_H #define DLPORTIO_DRIVER_H
typedef WINAPI void (*DlPortWritePortUchar_t) (unsigned port, uint8_t data); typedef WINAPI uint8_t(*DlPortReadPortUchar_t) (unsigned p); typedef WINAPI void (*DlPortWritePortBufferUchar_t) (unsigned p, uint8_t * buf, int len); typedef WINAPI void (*DlPortReadPortBufferUchar_t) (unsigned p, uint8_t * buf, int len); typedef WINAPI void (*DlPortWritePortUshort_t) (unsigned p, uint16_t data); typedef WINAPI uint16_t(*DlPortReadPortUshort_t) (unsigned p); typedef WINAPI void (*DlPortWritePortBufferUshort_t) (unsigned p, uint16_t * buf, int len); typedef WINAPI void (*DlPortReadPortBufferUshort_t) (unsigned p, uint16_t * buf, int len);
class dlportio_driver : public port_io_driver { public: static dlportio_driver *create();
/* ЛИШНЕЕ ПОСКИПАНО */
protected: HINSTANCE hdlportio;
#define _DL_PTR(_f_) _f_##_t _f_##_P
_DL_PTR( DlPortWritePortUchar ); _DL_PTR( DlPortReadPortUchar ); _DL_PTR( DlPortWritePortBufferUchar ); _DL_PTR( DlPortReadPortBufferUchar ); _DL_PTR( DlPortWritePortUshort ); _DL_PTR( DlPortReadPortUshort ); _DL_PTR( DlPortWritePortBufferUshort ); _DL_PTR( DlPortReadPortBufferUshort );
#undef _DL_PTR
}; и в соответствующем исходнике Цитата(dlportio_driver.cpp) dlportio_driver *dlportio_driver::create() { #define _DL_LOAD(_f_) \ do {\ pdl->_f_##_P = (_f_##_t)GetProcAddress(pdl->hdlportio, #_f_);\ if(pdl->_f_##_P == NULL) {\ delete pdl;\ return NULL;\ }\ } while(0)
dlportio_driver *pdl = new dlportio_driver;
pdl->hdlportio = LoadLibrary("DLportIO.dll"); if (pdl->hdlportio == NULL) { delete pdl; // "Can't load port library\n" return NULL; }
_DL_LOAD( DlPortWritePortUchar ); _DL_LOAD( DlPortReadPortUchar ); _DL_LOAD( DlPortWritePortBufferUchar ); _DL_LOAD( DlPortReadPortBufferUchar ); _DL_LOAD( DlPortWritePortUshort ); _DL_LOAD( DlPortReadPortUshort ); _DL_LOAD( DlPortWritePortBufferUshort ); _DL_LOAD( DlPortReadPortBufferUshort );
return pdl;
#undef _DL_LOAD } Ужас.... но буду принимать понемногу  По поводу bin я не нашел в IAR возможность записывать константы типа: 0b11111011 В ANSI C такого и нет, вроде, вот я и решил что IAR этот вариант представлени не поддерживает. Т. е. писать константы в hex 0xFB, или в DEC 251 соответственно. Или может там есть возможность как-то иначе но в поиск по Help ничего не дал. ???
|
|
|
|
|
Oct 28 2005, 05:33
|

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

|
Цитата(&-rey @ Oct 27 2005, 15:04) Ужас.... но буду принимать понемногу  По поводу bin я не нашел в IAR возможность записывать константы типа: 0b11111011 В ANSI C такого и нет, вроде, вот я и решил что IAR этот вариант представлени не поддерживает. Т. е. писать константы в hex 0xFB, или в DEC 251 соответственно. Или может там есть возможность как-то иначе но в поиск по Help ничего не дал. ??? В порядке убывания разумности с моей точки зрения. 1) писать не 0b0010011 и не 0x23, а (1<<ENABLE) | (3<<MODE), а то придётся помнить наизусть значение всех битов всех регистров либо постоянно лазить в документацию. Заодно надо будет меньше комментариев вида /* ставим в режим MODE3 и разрешаем работу */ писать - оно по самому выражению будет видно. 2) привыкнуть к HEX-формату и не морочить голову об 0bxxxxxxxx 3) поискать по интернету готовый файл с любопытным #define BIN(a), который применяется как BIN(00010011) а на самом деле при помощи уже упомянутого 0##a приклеивает к аргументу a лидирующий 0 для гарантии восьмеричности числа, после чего при помощи операций %8 /8 выделяет отдельные цифры и составляет двоичное число. Поскольку всё константы - это операция времени компиляции и код эффективный. 4) Поискать по интернету готовый файл с 256-ю #defin-ами вида #define b00000000 0x00 #define b00000001 0x01 и т.д. (внимание на то, что начинается с b, а не с нуля)
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 28 2005, 06:12
|

Странник
   
Группа: Свой
Сообщений: 766
Регистрация: 29-08-05
Из: Екатеринбург
Пользователь №: 8 051

|
Цитата(ReAl @ Oct 28 2005, 10:33) 3) поискать по интернету готовый файл с любопытным #define BIN(a), который применяется как BIN(00010011) Зачем же так далеко посылать ;-) Код #define BIN2BYTE(a) ( ((0x##a##L>>21) & 0x80) + ((0x##a##L>>18) & 0x40) \ + ((0x##a##L>>15) & 0x20) + ((0x##a##L>>12) & 0x10) \ + ((0x##a##L>>9) & 0x08) + ((0x##a##L>>6) & 0x04) \ + ((0x##a##L>>3) & 0x02) + (0x##a##L & 0x01))
--------------------
"Как много есть на свете вещей, которые мне не нужны!" Сократ
|
|
|
|
|
Oct 28 2005, 12:11
|

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

|
Цитата(spf @ Oct 28 2005, 09:12) Цитата(ReAl @ Oct 28 2005, 10:33) 3) поискать по интернету готовый файл с любопытным #define BIN(a), который применяется как BIN(00010011) Зачем же так далеко посылать ;-) А мне оно ненадо, я в пределах пунктов 1) и 2) работаю. Увидел, идею запомнил, писать в форум из головы влом (а сам макрос не сохранял за ненадобностью).
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 1 2005, 06:28
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Всем Спасибо за ответы, но проблема bin формата для меня не столь важна, просто если бы было, хорошо, а раз нет, то и ладно. Жить можно. В любом случае на примерах посмотрел как пишут макросы. Вот снова копался в форумах и нашел такое: от haker fox Цитата(haker_fox @ Oct 21 2005, 02:26) #ifndef CONST_H //если константа не определена, то #define CONST_H //определить константу //Код хедера #endif Когда компилятор будет во-второй раз цеплять хедер, он его не подцепит, т.к. константа CONST_H уже определена (при первом проходе) Вместо CONST_H соответственно для другого файла - другое имя, например MAIN_H и от IgorKossak [quote=IgorKossak,Oct 24 2005, 10:55] Никто почему-то не расскажет ещё об одной технике обьявления/определения переменных в хедерах. Помимо охранных констант, исключающих повторное включение файла иногда бывает удобно в одном файле и определять и обьявлять переменные (экземпляры класса). Код #ifndef _xxx_DEF ... unsigned int My_Int_Var; ... #else ... extern unsigned int My_Int_Var; ... #endif Константа _xxx_DEF обьявляется только в одном файле *.c, где происходит выделение под них памяти. Все же остальные файлы включающие данный хедер, будут видеть только обьявления. При желании можно написать макрос, который сделает всё это автоматически. мне как раз понадобилась данная рекомендация и я в *.h поставил так Код #ifndef _*_h #define _*_h char a=5; #else extern char a; #endif но компилятор ругается и говорит что переменная a определяется в 2-х файлах Но вроде бы должно было быть определение как переменной a только в одном файле, а в другом где подключен *.h уже просто определение как extern. получается что "защитный код" не работает. Ложки не существует ? или я что-то не так сделал ???
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|