logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Zwracanie zmiennej lokalnej przez funkcje [c][winavr]

AVRowiec 07 Sty 2010 15:48 2503 16
  • #1 7499180
    AVRowiec
    Poziom 18  
    char * fun(void)
    {
       char  temp[10];
       strcpy(temp,"napis");
    
      return temp;
    }


    Co zrobić żeby taka funkcja działała bezpiecznie i zawsze? żeby kompilator nie zwracał błędu
    main.c:1257: warning: function returns address of local variable
  • #2 7499207
    Ciapol
    Poziom 24  
    Będzie zwracał błąd. Bo tworzysz zmienną lokalną, której adres przekazujesz. Są dwa wyjścia:
    1. Zwracanie poprzez wartość.
    2. Zmienną temp definiujesz globalnie.


    Nie pisałem nic w winavr ale problem wydaje się dość standardowy.
  • #3 7499314
    AVRowiec
    Poziom 18  
    tzn jak mam zwrócić przez wartość? możesz to zapisać?

    globalnie nie chce bo to sie z celem mija.

    próbowałem ze static char temp[10]; ale nie działa. dlaczego?
  • #4 7499328
    MODI
    Poziom 17  
    dynamicznie zaalokuj pamięć
    pamietaj żeby potem zwolnić :)
    char * fun(void)
    {
       char * temp=malloc(10*sizeof(char));
       strcpy(temp,"napis");
    
      return temp;
    }


    ale bez kontrkstu trudno powiedzieć
  • #5 7499373
    AVRowiec
    Poziom 18  
    kurcze takie rzeczy na avr... sam nie wiem. jeszcze to zwalnianie pamięci potem, dużo kodu dużo zachodu, miejsca mało.

    nie zna ktoś innego sposobu?

    BTW dzięki za pomoc.
  • #6 7499411
    Ciapol
    Poziom 24  
    Podpowiedź kolegi wyżej trafna. Jak chcesz inaczej to pokaż kawałek kodu, w którym chcesz wykorzystać funkcję. Może uda się coś innego wymyślić.
  • #7 7499440
    AVRowiec
    Poziom 18  
    Chce zapisać i odczytać coś w EEPROMIE:

    odczyt:

    unsigned char * OpenString(unsigned char offset)
    {  
    static unsigned char  temp[12],i=0;
    for (char i=0; i<15; i++);//teoretycznie niepotrzebne
    i=0;
    
    while ((temp[i]!=0) && (i<12))
    {
       temp[i]=EEPROM_read(offset+i);
       i++;
    }
       temp[i]=0;//teoretycznie niepotrzebne
       
     return temp;
    }


    zapis:

    void SaveString(char offset, unsigned char * tekst)
    {
    
      for(char i=0; i<strlen(tekst); i++)
        EEPROM_write(offset+i, tekst[i]);
      
       
      EEPROM_write(i, 0);
    }


    użycie:

    SaveString(10,"kosmita");
    K(OpenString(10)); // na lcd
    Send(OpenString(10)); // na terminal


    po wykonaniu:

    na lcd: kosmita$%^$# - gdzie #$%% to krzaki

    na terminalu: 99999999999999999kosmita.....%#$%99999999999 - czyli nieskończone krzaki.

    Obsługa lcd i uartu standardowa i napewno działająca.

    Ma ktoś jakiś pomysł? :)
  • #8 7499492
    Ciapol
    Poziom 24  
    Tak jak wspomniałem wcześniej nic nie pisałem w winavr ale zastanawia mnie jedno:

    Dobrze zakończyłeś ciąg znaków?:
    Cytat:
    EEPROM_write(i, 0);
    Nie powinno być tam czegoś w rodzaju \n (end line - HEX: 0A; DEC: 10)
  • #9 7499526
    szelus
    Poziom 34  
    No, nie ma lekko:
    
    void OpenString(unsigned char *temp, unsigned char max_len, unsigned char offset)
    { 
        unsigned char  i=0;
        while (i<(max_len-1))
        {
            temp[i]=EEPROM_read(offset+i);
            if (temp[i] == 0)
            {
                return;
            }
            i++;
        }
        temp[i] = 0;
    }
    

    użycie:
    
    unsigned char temp[12];
    
    SaveString(10,"kosmita"); 
    OpenString(temp, 12, 10);
    K(temp);
    


    --- dodane
    Powyżej odniosłem się do tego, co napisałes, że chcesz uzyskać. Bo w tym, konkretnym, Twoim przykładzie static powinno załatwić sprawę. Jestes pewien, że nie zabrakło Ci pamięci?
    ---
    Uppss - tu jest problem:
    
    EEPROM_write(i, 0); 
    

    Powinno być:
    
    EEPROM_write(offset + i, 0); 
    

    Poza tym masz jeszcze pare drobnych błedów, np. potencjalnie piszesz w OpenString do temp[12], czyli już poza tablicą.
  • #10 7499639
    AVRowiec
    Poziom 18  
    wcześniej temp miało 15 pól. przenosząc tutaj przerobiłem.
    myśle że Twój pomysł szelus się sprawdzi. zaraz zobaczę.

    Dodano po 2 [minuty]:

    a jak działa taka funkcja itoa?
    sama funkcja zwraca ciąg ale robi to także przez bufor który trzeba sobie samemu zdefiniować out=itoa(buf,liczba,podstawa_liczby);
  • #11 7499685
    tmf
    VIP Zasłużony dla elektroda
    Trzeba jej podac adres bufora o dlugosci co najmniej takiej jaka jest maksymalna dlugosc konwertowanego ciagu. Dodatkowo funkcja zwraca adres bufora, co akurat jest malo uzyteczne :)
  • #12 7499689
    michalko12
    Specjalista - Mikrokontrolery
    AVRowiec napisał:
    wcześniej temp miało 15 pól. przenosząc tutaj przerobiłem.
    myśle że Twój pomysł szelus się sprawdzi. zaraz zobaczę.

    Dodano po 2 [minuty]:

    a jak działa taka funkcja itoa?
    sama funkcja zwraca ciąg ale robi to także przez bufor który trzeba sobie samemu zdefiniować out=itoa(buf,liczba,podstawa_liczby);


    Pierwszy link w google
    Link
  • #13 7499861
    AVRowiec
    Poziom 18  
    funkcja szelus'a jest dobra ale:

    na terminalu pojawia się:
    kosmita˙˙˙˙
    na lcd podobnie
    te kropeczki to 0xFF

    taki zabieg nie pomógł:
    
    void SaveString(char offset, unsigned char * tekst)
    {
    
      for(char i=0; i<strlen(tekst); i++)
        EEPROM_write(offset+i, tekst[i]);
      
       
      EEPROM_write(i, 0); EEPROM_write(i+1, 0xFF); EEPROM_write(i+2, 0x00); EEPROM_write(i+3, 0);
    }


    dlaczego?

    Dodano po 2 [minuty]:

    michalko12 mnie interesuje jak taka funkcja działa w środku że zwraca ciąg bez problemu. ciekawe czy gdybym dał u siebie return temp to czy by działało..
  • #14 7499918
    tmf
    VIP Zasłużony dla elektroda
    A nie mozesz odczytac EEPROM programatorem i sprawdzic czy masz skaszaniony zapis, czy odczyt? Byloby latwiej.
    Co do wrojej funkcji to jest w niej blad, dziwne, ze kompilator tego nie zglasza - char i jest zdefiniowane tylko w obrebie for, poza petla nie istnieje, wiec kolejne zapisy moga byc bledne. No i jesli tekst jest w formacie ASCIZ to wystarczy, ze warunek w petli zmienisz na <= i to zero sie skopiuje automatycznie.
  • #15 7499920
    AVRowiec
    Poziom 18  
    
    unsigned char * OpenString(unsigned char offset, unsigned char * temp, unsigned char max_len)
    {  
    unsigned char i=0;
    
    while (i<max_len-1)
    {
       temp[i]=EEPROM_read(offset+i);
       if (temp[i]==0) return temp;
       i++;
    }
       temp[i]=0;//teoretycznie niepotrzebne
       
     return temp;
    }

    
    SaveString(10,"kosmita");SaveString(30,"biribomba");
    char temp[12];
    OpenString(10,temp,12);
    SendAT(temp);
    K(temp);
    SendAT(OpenString(30,temp,12));
    K(OpenString(30,temp,12));
    


    działa i jedno i drugie wywołanie

    TYLKO SKĄD TE KROPOKI SIE BIORĄ?!?!?

    Dodano po 10 [minuty]:

    tmf - racja.

    poprawiłem i kropek nie ma ale za to zniknął pierwszy z zapisanych łańcuchów

    
    void SaveString(char offset, unsigned char * tekst)
    {
     char i=0;
      for( i=0; i<=strlen(tekst); i++)
        EEPROM_write(offset+i, tekst[i]);
      
      EEPROM_write(i, 0); 
    }


    Działa przez wywołanie:

    K(OpenString(30,temp,12));

    nie działa w taki sposób:

    char temp[12];
    OpenString(10,&temp,12); // próbowałem z & i bez i to samo
    K(temp);
  • Pomocny post
    #16 7500398
    michalko12
    Specjalista - Mikrokontrolery
    AVRowiec napisał:

    poprawiłem i kropek nie ma ale za to zniknął pierwszy z zapisanych łańcuchów

    
    void SaveString(char offset, unsigned char * tekst)
    {
     char i=0;
      for( i=0; i<=strlen(tekst); i++)
        EEPROM_write(offset+i, tekst[i]);
      
      EEPROM_write(i, 0); 
    }


    Działa przez wywołanie:

    K(OpenString(30,temp,12));

    nie działa w taki sposób:

    char temp[12];
    OpenString(10,&temp,12); // próbowałem z & i bez i to samo
    K(temp);


    W SaveString na końcu piszesz 2 razy '\0'

    
    void SaveString(char offset, unsigned char * tekst)
    {
    	while(*tekst)
    	{	
    		EEPROM_write(offset++, *tekst);
    		tekst++;
    	}
    	EEPROM_write(i, 0); 
    }


    A w załączniku masz źródło itoa jeśli Cię jeszcze interesuje.
  • #17 7500599
    AVRowiec
    Poziom 18  
    dziękować :)
    ale asemblera nie znam.

    wiem że dwa razy jest zero dodawane. ale nie powinno to powodować nie wyświetlania się znaku.

    dzieki za wersje ze wskaźnikami. też taką miałem pierwotnie. sprawdze jeszcze raz na tej Twojej.
REKLAMA