Pobranie C-STRINGU jako argument

0

Witam

Otóż problem jest następujący : Pisze funkcje dla mikroprocesora który toleruje tylko czyste C . Potrzebuje funkcje AddText , która zapisze string do pamięci urządzenia , oraz dodatkowo za argumenty przyjmuje kolor tla oraz samego tekstu . W czym problem ?

Otóż jak jak wywołam funkcje AddText("AAAA", kolor_1 , kolor_2 ); , to chyba nie bardzo powinienem przepisywać adres który podam w argumencie do jakiej globalnej tablicy wskaźników ? Aktualnie mam zrobione jako : Wewnątrz funkcji , liczę ile danych elementów ma C-STRING , później dla takiej liczby ( już łącznie z nullem ) "dzierżawie" pamięć za pomocą malloc(ilosc liter+null) . Teraz przepisuję wszystkie litery za koleją pod nowy adres zwrócony przez malloc i dopiero ten adres zapisuje globalnie .

Pytanie teraz , czy jest to konieczne ?

0

Niekoniecznie. Wszystko zależy od tego co właściwie ma robić ta metoda i skąd ma pobierać dane.
Jeśli jesteś pewny, że dodawane teksty istnieją przez cały czas gdy będziesz z nich korzystał (stałe tekstowe się kwalifikują) to wystarczy, że będziesz pamiętał wskaźnik do tego napisu.
Niestety na podstawie twojego mętnego opisu nie można powiedzieć wiele więcej.

0

Dzięki , za odpowiedź .

Ogólnie rozchodzi się o sterowanie wyświetlaczem LCD . Mam w pamięci tablice obiektów struktury której jednej ze składników jest adres do w/w ciągu znaków . Innymi składnikami są kolor tekstu , tła itd.
Ale oprócz dodania tekstu , ustalania kolorów etc , trzeba jeszcze w paru miejscach to zasygnalizować ( dodanie nowej wiadomości ) . Więc chciałem napisać funkcję która za argumenty pobierze tylko najbardziej niezbędne rzeczy a w środku zajmie się całą resztą.

I czy teraz dla funkcji która za argument pobiera unsigned char * , a wywołana z argumentem " ALARM " mogę ten adres zapamiętać w globalnej tablicy ? Podczas działania programu chyba mogą zostać zapisane ? Sam mikroprocesor ma tylko 1 KB pamięci RAM ....

0

Nienawidzę ogólników, bo mam wrażenie, że ktoś mnie prosi o napisanie rozdziału do książki o programowaniu.
Konkretów = Fragmentu kodu z krótkim opisem.

Jeśli tworzysz napisy w czasie działania programu, stworzenie kopi lub przejęcie własności nad napisem może być konieczne. Jeśli są to tylko stałe tekstowe, spokojnie możesz użyć jedynie wskaźników do napisów.

0

Jeśli tak to zabrzmiało to przepraszam , a żadnego kodu nie potrzebuję . Dodawane teksty są podczas pracy programu , i wszystko się dzieje w pamięci RAM a nie FLASH więc tak jak Pan mówi , i tak jak przeczuwałem na początku trzeba będzie dodatkowo string kopiować pod zarezerwowaną pamięć .

0

a w czym te dodawane teksty sa logicznie umieszczane? w jakims wspolnym duzym buforze? czy kazdy jest alokowany osobno? skoro one sa juz w RAM to moze wystarczy jedynie przekazac wskaznik i go 'po swojej stronie' zbugic, liczac ze metoda addtext go zwolni? czy tez Tobie caly czas chodzi o metode ktora dany napis wyryje wewnatrz FLASH i masz na mysli kopiowanie napisow -do- bloku pamieci FLASH ? wypowiadasz sie na razie tak nieskladnie ze trudno sie domyslic dokladnie co zamierzasz:/

0

Dzięki za pomoc , chociaż już nie wiem jak łatwiej to wytłumaczyć . Może zejdźmy z pamięci FLASH , bo ona w mikrokontrolerze podczas pracy może być tylko z poziomu bootloadera , więc jakikolwiek późniejszy zapis do niej odpada ... i właśnie do tego zmierzam .

Funkcja : AddText(unsigned char * );

Czy teraz jeśli wywołam tą funkcje ( jeszcze przed kompilacją , i wrzuceniem kody wynikowego do mikroprocesora ) , jako AddText("ALARM_1") a w niej :

static unsigned char stale_tekstowe = 0 ;

globalna_tablica_tekstow[stale_tekstowe++] = adres do pierwszego elementu przekazany przez argument f.

To czy kiedy procek będzie potrzebował coś później liczyć to po tym obszarze mi skakać nie będzie ( bo przeciez wszystkie dane sa trzymane w pamięci RAM ) ? Z tego co sie orientuje funkcja malloc mi to zagwarantuje .

0

Aaa, czyli Ty się obawiasz, że wskaźnik na stałą dosłowną w pewnym momencie się zdezaktualizuje, bo kompilator uzna, że już nie jest potrzebna, i w czasie wykonania zostanie ona nadpisana? Zasadniczo stawiam duży palec u prawej nogi, że to nie nastąpi. Kompilator literały umieszcza sobie w obszarze oznaczonym jako "nienaruszalny" i są one w całości zachowane przez cały cykl życia programu. Jeśli ta tablica jest używana tylko do odczytu, to nie kopiuj tekstów, tylko same wskaźniki.

Ewentualnie, jak chcesz mieć gwarancję wyższą, niż mój palec, to podaj nazwę kompilatora. Spróbuje się zobaczyć w dokumentacji, czy nie wsadza ich na stos. IMO jest to skrajnie wątpliwie, ale możliwe - i jak rozumiem ta właśnie niepewność cię nęka?

0

Dzięki za konkretną odpowiedź !

GNU Compiler Collection (GCC) 4.3.2 - o to chodzi ? Środkoisko to WinAvr . O właśnie problemu który Pan przedstawił mnie męczy równie mocno ! Zakładam ,że jest Pan "Wielką Stopą" , i pójdę na ten palec :)

A co jeśli przykładowy string będzie zapisany powiedzmy od komórki 0x60 do 0xXX w pamięci RAM , i czy jeśli ten obszar nie będzie rezerwowany przez funkcje malloc to po pewnym czasie działania programu kompilator nie stwierdzi , że ten obszar już mi potrzebny nie jest , i nawkłada tam wyników obliczeń/argumentów etc ? ( String umieszczany już w main'nie , nie globalny ).

Dzięki , za odpowiedzi i gratuluje wiedzy !

0

Ok, no to tak. Dla GCC mamy strasznie jasną sytuację, bo mamy gwarancję standardu, GCC, szczególnie w wersji 4.x.x GCC zachowuje się poprawnie. Możesz bez żadnych obaw polegać na wskaźnikach, jeśli będziesz funkcji używał na 2 sposoby:

void some_function() {
   // podajesz literał
   AddText("Foo");

   // podajesz wskaźnik na literał
   const char* temp = "Bar";
   AddText(temp);
   }

Po prostu - wskaźnik na literał jest lokalny - ale sam literał jest statyczny, jest cały czas.
Uwaga, ważne jest, że nie możesz podawać tablicy, która została stworzona jawnie na stosie:

void foo() {
   // będzie SYF!
   char buffer[] = "Bar";
   AddText(buffer);
   }

Wyjątek to funkcja main - jeśli utworzyłeś zmienną lokalną w main, możesz ją podawać do woli - ona też nie zostanie zniszczona. Cykl życia zmiennej to zasięg bloku - dopóki main się nie zakończy, zmienna będzie istnieć, i nie zostanie naruszona.

int main() {
   // będzie OK
   char main_buffer[] = "Bar";
   AddText(main_buffer);
   }

i teraz - jeśli piszesz tylko tak, to nie musisz wiedzieć, że string jest zapisany od 0x60 do 0x80. Niech będzie - Ty masz gwarancję, że kompilator ZAWSZE będzie uważał, że te obszary są potrzebne. Argumenty/wyniki nawet nie zbliżają się do sekcji z danymi statycznymi/kodem - nic nie namieszają. Nigdy stos też się tak nie zwinie, żeby nadpisano zmienne lokalne z main.

0

Dzięki ! Konkretna odpowiedź , rozwiewająca wszelkie wątpliwości !

Swoją drogą bałem się o zakresy , a przecież fakt zakres main'a się nie skończy ...

Stokroć dzięki koledze jeszcze raz !

1 użytkowników online, w tym zalogowanych: 0, gości: 1