|
diod.club
Проектирование, изготовление, ремонт и обслуживание электроники
|
Помощь
|
 |
Без описания |
Поиск в теме | Версия для печати |
|

Отправлено: 14 Апреля, 2015 - 11:03:02
|
|
Junior Member (67)
Откуда: Хорол, Україна
Репутация: 1
|
|
Знатоки Си, обьясните, какое преимущество дает применение указателей вместо прямого обращения к пременной. С массивами, там более-менее понятно.
Вот, допустим, обьявляю я указатель на переменную
int a;
int* pa = &a;
и что дальше?
ну могу я в коде присвоить значение переменной а через указатель
*pa = 100;
и какой выиграш это мне дает относительно прямого присвоения a=100;?
Можно, конечно, этот указатель переуказать на другую переменную, но опять-же зачем?
Вот такой вот вопрос.  |
|
|
|
Advanced Member (312)
Откуда: Kyiv
Репутация: 6
|
|
В таком простом примере никакого преимущества нет, скорее только недостатки. Практическая польза от указателей появляется в более сложных случаях. Например, удобно использовать указатели на структуры при разборе буфера принятых данных. Также удобно работать с указателями при работе с различными списками объектов, более крупных, чем просто переменная типа int
Указатели удобны при передаче в функцию объектов большого размера, чтобы не создавалась копия такого объекта, а также для возврата из функции более чем одного значения. |
Леонид Иванович
|
|
|
|
|
Super Member (860)
Откуда: Minsk
Репутация: 35
|
|
Где-то читал, что все люди делятся на две категории: которые понимают указатели Си, и которые не понимают. Я себя отношу ко второй категории. Поэтому использую указатели крайне редко. Вообще, их значимость для языка Си очень преувеличена, они лишь запутывают исходники и делают программы менее безопасными.
Беглый просмотр своих исходников выявил считанные места, где используются указатели. Например, когда функция должна возвращать более одного значения:
CODE:void Menu_GetVStep(char *s1, char *s2)
При работе с буфером:
CODE:static char *TxPtr; //указатель буфера передачи
...
char data = *TxPtr++; //чтение байта из буфера
...
Классический пример - вывод строки:
CODE:void LCD_PutString(char __flash *s)
{
while(*s) LCD_PutChar(*s++);
} |
|

Отправлено: 14 Апреля, 2015 - 12:23:36
|
|
Junior Member (67)
Откуда: Хорол, Україна
Репутация: 1
|
|
koyodza, Леонид Иванович, большое спасибо!
Теперь понятно. Куда попало их тыкать мало того, что безсмысленно, но и вредно.
А там, где он нужен, он сам напросится
Но пока что я тоже в категории тех, кто их не понимает , вернее не приходилось использовать в своем коде.(Отредактировано автором: 14 Апреля, 2015 - 17:52:47) |
|

Отправлено: 12 Августа, 2015 - 11:04:13
|
|
с указателями есть интересный примерчик
unsigned char TxField[512]; // приемный буфер, читаем из uart
struct RDM_Packet *rdm; //некая структура пакета принятого по uart
rdm = (struct RDM_Packet *)&TxField; // накладываем структуру на входной буфер
rdm->DestID[4]= 0xFF; // а тут самое интересное, работаем с элементами структуры
rdm->DestID[5]= 0xFF;
rdm->CmdCls = DISC_CMD;
rdm->PID = DISC_UNIQUE_BRANCH;
Есть еще UNION
классная вещь когда надо обратится по байтно и побитно к переменной
либо рассматривать рассматривать 4 байта как uint32_t либо как float kb как массив из 4-х uint8_t
пример не выложу нету под рукой(Отредактировано автором: 12 Августа, 2015 - 11:19:59) |
|
|
|
Advanced Member (312)
Откуда: Kyiv
Репутация: 6
|
|
Выше я упоминал об этом ( указатели на структуры при разборе буфера принятых данных), хотя и не приводил пример кода. Но на некоторых платформах нужно помнить, что обращение к невыровненным данным может приводить к исключениям, в частности на многих старых ARM
Средствами языка С этого можно избежать, если определить структуру как packed
Битовые поля и UNION к указателям отношения не имеют. Кстати, сами битовые поля часто обрабатываются крайне неэффективно, тут нужно смотреть какое ядро и какой компилятор.(Отредактировано автором: 12 Августа, 2015 - 12:48:17) |
|

Отправлено: 02 Декабря, 2015 - 21:02:12
|
|
Junior Member (67)
Откуда: Хорол, Україна
Репутация: 1
|
|
Что значит сообщение компилятора
in expansion of macro 'BT_SEL'
в 2х строках этого кода:
CODE:
if (BT_SEL)
{
sei();
Beep(250);
DotDisp = 1;
ReCode(NumVer,3);
while (BT_SEL){};
DotDisp = 0;
cli();
SetSIStart = 1;
}
сам макрос
CODE:#define BT_SEL PINC&(1<<PINC2) == 0 //кнопка select/ok |
|
|
|
Advanced Member (312)
Откуда: Kyiv
Репутация: 6
|
|
А как определен PINC2 ? |
|

Отправлено: 02 Декабря, 2015 - 21:12:32
|
|
Junior Member (67)
Откуда: Хорол, Україна
Репутация: 1
|
|
Вот кусок с iom168pa.h:
Цитата:
#define PINC _SFR_IO8(0x06)
#define PINC6 6
#define PINC5 5
#define PINC4 4
#define PINC3 3
#define PINC2 2
#define PINC1 1
#define PINC0 0
или имеется в виду направление вход/выход?
Вродь тоже нормально, вход с пуллапом
CODE:
// Port C initialization
// Function: Bit6=In Bit5=Out Bit4=Out Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC6) | (1<<DDC5) | (1<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=0 Bit4=0 Bit3=P Bit2=P Bit1=P Bit0=P
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0);
P.S. на всякий случай уточню, что это именно сообщение, а не ошибка.
Upd
Заменил
CODE:#define BT_SEL PINC&(1<<PINC2) == 0
на
CODE:#define BT_SEL !(PINC&(1<<PINC2))
сообщение пропало(Отредактировано автором: 02 Декабря, 2015 - 21:45:06) |
|
|
|
Advanced Member (312)
Откуда: Kyiv
Репутация: 6
|
|
Вероятно это предупреждение о неявном преобразовании типов: (1<<PINC2) имеет разрядность int по-умолчанию (для IAR AVR это 16 бит), а PINC определен скорее всего как volatile unsigned char или подобным образом, т.е. 8 бит |
|

Отправлено: 08 Января, 2016 - 22:40:42
|
|
Junior Member (67)
Откуда: Хорол, Україна
Репутация: 1
|
|
Таки да, скобочки, попробовал с ними, все норм.
Сейчас уже не актуально, но на будущее пригодится.
Upd. 20.02.2016
Есть вопрос по функциям
CODE:void eeprom_write_word (uint16_t *__p, uint16_t __value);
void eeprom_update_word (uint16_t *__p, uint16_t __value);
Эти функции блокируют прерывания при записи, или их нужно окружать cli(); и sei();?(Отредактировано автором: 20 Февраля, 2016 - 11:40:16) |
|
Поиск в теме | Версия для печати |
Страниц (1): [1] |
Сейчас эту тему просматривают: 1 (гостей: 1, зарегистрированных: 0) |
« Программирование » |
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
|
  |
|