Указатели
Достаточно важным элементом программирования микроконтроллеров являются указатели. Они позволяют избавиться от указания на внешние переменные, например extern uint_8 a. Функции можно реализовать более гибкими. Появляется возможность передать массив, или переменную в функцию с возможностью ее изменения.
void Swap(int a, int b) // здесь аргументы - значения
{int t = a; a = b; b = t; }
// вызов Swap(x,y); // эта функция на самом деле работать не будет
void Swap(int *a, int *b) // здесь аргументы - указатели
{int t = *a; *a = *b; *b = *t; }
// вызов Swap(&x,&y); // явным образом указываются адреса переменных
void Swap(int &a, int &b) // здесь аргументы - ссылки
{int t = a; a = b; b = t; }
// вызов Swap(x,y);
*pn = 5; // Разыменование указателя и присваивание значения 5.
n = *pn; // Присвоить n то значение (5), на которое указывает pn.
free(pn); // Освободить занятую память.
pn = &n; // Присваивает указателю pn адрес переменной n(указатель будет ссылаться на n).
n = 7; // *pn тоже стало равно 7
Поскольку в Си функции в качестве своих аргументов получают значения параметров, нет прямой возможности, находясь в вызванной функции, изменить переменную вызывающей функции. В программе сортировки нам понадобилась функция swap, меняющая местами два неупорядоченных элемента. Однако недостаточно написать
swap(a, b)
где функция swap определена следующим образом:
void swap(int x, int y) /* НЕВЕРНО */
{
int temp;
temp = x;
x = y;
y = temp;
}
Поскольку swap получает лишь копии переменных a и b, она не может повлиять на переменные a и b той программы, которая к ней обратилась.
Чтобы получить желаемый эффект, вызывающей программе надо передать указатели на те значения, которые должны быть изменены:
swap(&a, &b);
Так как операция & получает адрес переменной, &a есть указатель на a. В самой же функции swap параметры должны быть объявлены как указатели, при этом доступ к значениям параметров будет осуществляться косвенно.
void swap(int *px, int *py) /* перестановка *px и *py */
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Вот только возникает проблема. Пример функции
//считывает из памяти системные константы(калибровка, другие значения)
void boot_constanta()//uint8_t *sys_const,uint16_t *u_param)
{
extern uint8_t calibr_cells[];
extern uint16_t u_param[];
//читаю из EEPROM калибровочные константы
for (uint8_t i=0;i<5;i++)
{
//calibr_cells[i]=ee_read(i);
calibr_cells[i]=ee_read(i);
//если память чистая
if (calibr_cells[i]==0xFF) {calibr_cells[i]=0;}
}
uint8_t tmpH,tmpL,k=0;
//читаю из еепром значения напряжений 6H7L,8H9L,10H11L
for(uint8_t i=6;i<12;i+=2)
{
tmpH=ee_read(i);
tmpL=ee_read(i+1);
//собираем int16_t из двух int8_t. "С" очень криво делает эту операцию
asm volatile( "clr %A[RES]" "\n\t"
"clr %B[RES]" "\n\t"
"mov %A[RES],%[Low]" "\n\t"
"mov %B[RES],%[Hi]" "\n\t"
:[RES]"=&d"(u_param[k]):[Hi]"r"(tmpH),[Low]"r"(tmpL)
);
k++;
}
}
Если использовать extern-Тогда код на 6 байт меньше! с указателями больше
Размер кода с использованием указателей в функции динамической индикации, и преобразования чисел 3222 , с использованием extern 3184, экономия 38 байт.
|