Jak používat ukazatele ve firmwaru v jazyce C.
V tomto článku probereme operátory ukazatele, aritmetiku ukazatele a dvě situace, kdy ukazatele mohou vylepšit váš kód.
podpůrné informace
Práce s hodnotami ukazatele
Změňte ukazatel a odkazování
K ukazateli jsou přidruženy dvě hodnoty. První je adresa paměti uložená v samotném ukazateli a druhá informace uložená v této adrese paměti. Chcete-li změnit adresu uloženou v proměnné ukazatele, jednoduše použijte znaménko rovná se:
RxByte_ptr = 0x40;
K přístupu k datům uloženým v adrese ukazatele použijte hvězdičku. To funguje jak pro čtení, tak pro psaní.
ReceivedData = * RxByte_ptr;
* TxByte_ptr = TransmitData;
Přístup k hodnotě, na kterou ukazuje ukazatel, se nazývá opětovné odkazování a hvězdička (při použití s ukazateli) se nazývá referenční operátor.
Zjištění adresy proměnné
Důležitým detailem o používání ukazatelů je operátor „směr C“; Symbolem je &. Ačkoli je & spojeno spíše s normálními proměnnými než s ukazateli, stále to považuji za „operátor ukazatele“, protože jeho použití úzce souvisí s implementací ukazatele.
Je-li před název proměnné umístěn znak &, použije program místo hodnoty proměnné adresu proměnné.
To vám umožní vložit adresu proměnné do ukazatele, i když nemáte tušení, kde se proměnná bude nacházet v paměti. Použití operátoru & je ukázáno v následujícím fragmentu kódu, který slouží také jako souhrn základního použití ukazatele.
char DisplayChar;
char TestingVariable;
char * DisplayChar_ptr;
DisplayChar = 0x41;
DisplayChar_ptr = & DisplayChar;
TestingVariable = * DisplayChar_ptr;
* DisplayChar_ptr = 0x42;
TestingVariable = DisplayChar;
Zde je podrobné vysvětlení toho, co tento kód dělá:
DisplayChar = 0x41;
Proměnná DisplayChar nyní obsahuje hodnotu odpovídající ASCII “A”.
DisplayChar_ptr = & DisplayChar;
Ukazatel (DisplayChar_ptr) nyní obsahuje adresu proměnné DisplayChar. Nemáme tušení, co je tato adresa, takže neznáme číslo uložené v DisplayChar_ptr. Také to nemusíme vědět; Práce tohoto překladače není naše.
TestingVariable = * DisplayChar_ptr;
TestingVariable má nyní hodnotu proměnné DisplayChar, tj. 0x41.
* DisplayChar_ptr = 0x42;
Ukazatel jsme použili ke změně hodnoty uložené v adrese odpovídající proměnné DisplayChar; nyní je to 0x42, toto je ASCII ‘B’.
TestingVariable = DisplayChar;
TestingVariable má nyní hodnotu 0x42.
Aritmetika ukazatele
Proměnná C má často hodnotu proměnné a proměnné ukazatele nejsou výjimkou. Běžné aritmetické operace používané ke změně hodnoty ukazatele jsou sčítání (například TxByte_ptr = TxByte_ptr + 4), odčítání (TxByte_ptr = TxByte_ptr – 4), přírůstek (TxByte_ptr ++) a dekrementace (TxByte_ptr ++), kde mají data dva stejné. Dokud je možné odstranit jednu značku z druhé. Nelze však přidat ukazatel na jiný ukazatel.
Aritmetika ukazatele není tak jednoduchá, jak se zdá. Předpokládejme, že máte ukazatel s dlouhým datovým typem. Ladíte nějaký kód a právě děláte jeden průchod z rutiny, která tento ukazatel opakovaně zvyšuje. Všimněte si, že hodnota ukazatele se nezvyšuje s každým přírůstkem ve vašem pozorovacím okně. Co se to tu děje?
Pokud na odpověď nemůžete snadno myslet, měli byste věnovat trochu více času přemýšlení o povaze ukazatelů. Ukazatel v tomto kódu se používá s dlouhými proměnnými, tj. Proměnnými, které spotřebovávají čtyři bajty paměti. Když zvětšíte ukazatel, ve skutečnosti nechcete, aby se hodnota ukazatele zvýšila o jednu pozici v paměti (za předpokladu, že je paměť organizována v bajtech). Místo toho chcete, aby se zvýšil o čtyři umístění paměti, aby se zobrazila další dlouhá proměnná. Kompilátor to ví a odpovídajícím způsobem změní hodnotu ukazatele.
Totéž platí, když přidáte nebo odečtete číslo od ukazatele. Adresa uložená v kurzoru nemusí nutně zvyšovat nebo snižovat toto číslo; místo toho se toto číslo zvýší nebo sníží vynásobeno velikostí datového typu ukazatele v bajtech.
Ukazatele a pole
Ukazatele a sekvence spolu úzce souvisejí. Když deklarujete pole, ve skutečnosti vždy vytvoříte pevný ukazatel obsahující počáteční adresu pole a indexovou notaci, kterou používáme pro přístup k prvkům pole, lze také použít s ukazateli.
Předpokládejme například, že máte aktuálně znakový ukazatel s názvem TxBuffer s adresou 0x30. Fragment kódu níže ukazuje dva ekvivalentní způsoby přístupu k datům na adrese 0x31.
TxByte = * (TxBuffer + 1);
TxByte = TxBuffer[1];
Kdy se používají ukazatele?
V této části bych chtěl krátce zmínit dvě situace kódování, které mohou těžit z použití ukazatelů a které jsou zvláště důležité pro vestavěné aplikace.
Ukazatel versus matice
První přirozeně navazuje na diskusi v předchozí části. Ukazatele poskytují alternativní metodu manipulace s daty uloženými ve formátu pole. Přístup ukazatele může být intuitivnější nebo užitečnější v konkrétním kontextu rutiny.
V některých případech však aplikace založená na ukazatelích může poskytnout rychlejší kód. Jak jsem pochopil, v minulosti to platilo více, než kompilátoři byli extrémně propracovaní a měli tak rozsáhlou optimalizaci. V kontextu integrovaného vývoje si však myslím, že existují situace, kdy ukazatele mohou dosáhnout znatelného zlepšení rychlosti provádění. Pokud se opravdu snažíte získat minimální počet hodinových cyklů potřebných ke spuštění konkrétní části kódu, stojí za to vyzkoušet ukazatele.
Předávání ukazatelů na funkce
Rozsáhlé používání funkcí vám pomůže psát organizovaný a modulární kód. To je v pořádku, ačkoli C ukládá omezení, které může být v některých případech zvláštní: funkce může mít pouze jednu návratovou hodnotu. Jinými slovy, Změna Pouze jedna proměnná, pokud nepoužíváte ukazatel.
Tato technika funguje následovně:
- Přidejte ukazatel jako jeden ze vstupů funkce.
- Pomocí operátoru & předejte funkci proměnné adresu.
- Uvnitř funkce se adresa proměnné stane hodnotou ukazatele a funkce použije referenční operátor ke změně hodnoty původní proměnné.
- Přestože se původní proměnná nezmění přímoPomocí návratové hodnoty kód, který následuje po funkci, předpokládá, že se změní hodnota proměnné.
Zde je příklad:
#define STEPSIZE 3
void IncreaseCnt_and_CheckLED (char * Count)
{
* Count = * Count + STEPSIZE;
si (LED == VERDADERO)
volver VERDADERO
más
falso retorno;
}
int main ()
{
char RisingEdgeCount = 0;
bit LED_State;
...
...
LED_State = IncreaseCnt_and_CheckLED (& RisingEdgeCount);
...
...
}
výsledek
Doufám, že máte jasnou představu o tom, co jsou ukazatele a jak s nimi začít ve firmwaru jazyka C. Pokud existují aspekty vestavěného jazyka C, o kterých byste chtěli diskutovat v budoucích článcích, komentáře níže.

