AVR GCC - Einfache Stringmanipulation

Gast #4257992
Lesenswert?

Hallo zusammen,

der folgende Codeschnipsel stammt aus der Frequenzaufbereitung eines 
Amateurfunkgerätes, das ich gerade baue. Verwaltet werden damit einzelne 
virtuelle Oszillatoren, deren Frequenz dann jeweils in ein DDS 
eingelesen wird.
1
void show_vfo(int vfo_num)
2
{
3
    char *vfo_str = "VFO  ";
4

5
    *(vfo_str + 4) = vfo_num + 65;
6
    lcd_put_string(x0 + 2, y0 + 2, vfo_str, 1, DARKBROWN, LIGHTGREEN);
7
}

Angezeigt werden soll ein String "VFO X", wobei der Buchstabe X durch 
einen beliebigen Buchstaben ersetzt werden soll. Also "VFO A", "VFO B" 
etc. etc. Die übergebenen Zahlenwerte in vfo_num reichen von 0 bis 12. 
Analog dazu soll der Kennbuchstabe des Frequenzspeichers auf der 5. 
Stelle des String landen.

Wenn ich den Code in meinem alten "Turbo C"-Compiler teste, funktioniert 
es. Beim GCC für AVR (WINAVR 20100110) aber nicht. Das Ganze als Array 
ginge zwar auch, will ich aber nicht. Den Buchstaben separat hinter 
"VFO" schreiben wäre auch eine Alternative, aber ich will wissen, warum 
das hier nicht tut.

Ich stehe gerade mal heftig auf dem Schlauch. Hilft mir jemand runter? 
;-)

Viele Grüße

Peter
(DK7IH)
Gast #4258008
Lesenswert?

Mit der Definition und Initialisierung
1
char *vfo_str = "VFO  ";


reservierst Du auf dem Stack nur 5 Zeichen (einschl. dem 
Nullterminator).
Garantiert ist jedenfalls nur diese Länge - mehr ist ja eigentlich auch 
nicht nötig. Das Du da noch Zeichen anfügen willst, weiß der Compiler 
nicht.
Gast #4258010
Lesenswert?

Ooops. Sorry.

Du reservierst nur einen Zeiger auf dem Stack der auf einen Bereich, der 
jedoch nur für 5 Zeichen ausgelegt sein muss, zeigt. Wenn Du da was 
anhängst, kann das schiefgehen. Geht es hier wohl auch.
Gast #4258016
Lesenswert?

das Problem sehe ich darin, das man die Daten nicht mainipulieren darf.

teste mal mit:
1
void show_vfo(int vfo_num)
2
{
3
    char vfo_str[] = "VFO  ";
4
    vfo_str[4] = vfo_num + 'A';
5
    lcd_put_string(x0 + 2, y0 + 2, vfo_str, 1, DARKBROWN, LIGHTGREEN);
6
}

beim PC können sie durchaus im Read-Only Ram liegen. Meist wird es zwar 
gehen aber zulässig dürfte es nicht sein.
Gast #4258018
Lesenswert?

1
char *vfo_str = "VFO  ";

deklariert einen Pointer auf ein (u.u. nicht beschreibbares 
String-Literal)

Probier stattdessen mal:
1
char vfo_str[] = "VFO  ";

Dies deklariert einen beschreibbaren Array, der mit "VFO  " 
initialisiert wird.
Gast #4258025
Lesenswert?

1
void show_vfo(int vfo_num)
2
{
3
    char vfo_str[] = "VFO  ";
4

5
    vfo_str[4] = vfo_num + 'A';
6
    //lcd_put_string(x0 + 2, y0 + 2, vfo_str, 1, DARKBROWN, LIGHTGREEN);
7
    puts(vfo_str);
8
}

Pointerversion macht auch PC Probleme.
#4258092
Lesenswert?

@ Peter Rachow (Gast)

>Hi zusammen, danke für Eure zahlreichen Rückmeldungen und die
>Erklärungen. Dann mache ich das mit dem Array.

Was spricht dagegen? Weil 6 Bytes auf dem Stack angelegt werden?
Was geht denn auf dem AVR gcc nicht? Kommen kryptische Zeichen raus?
Denn so oder so muss der avr gcc den String im RAM anlegen, im Flash 
geht ja nicht. Also muss auch eine Manipulation des Strings möglich 
sein.
#4258190
Lesenswert?

Peter Rachow schrieb:

> aber ich will wissen, warum
> das hier nicht tut.

Weil dein Pointer auf ein String-Literal zeigt und das per Definition 
für dich unberührbar ist.
Korrekt würdest du übrigens schreiben
1
    const char *vfo_str = "VFO  ";
womit sich dann auch der Rest erübrigt, denn dann würde dir der Compiler 
auf die Finger klopfen, wenn du versuchst einen char davon zu verändern.
Gewöhn dir an const korrekt zu arbeiten.
#4258211
Lesenswert?

Ja ja, schon gut.
Trotzdem, ist das nicht Performence hemmend weil vfo_str[] bei jedem 
Aufruf von show_vfo() auf dem Stack erzeugt (kopiert) werden muss? So 
kenne ich es aus der x86-Welt.

Wäre ein static vfo_str[] hier nicht besser? Er ändert ja sowieso immer 
nur ein Byte.
#4258237
Lesenswert?

Es geht um das Prinzip... ein dilettantischer Kollege hat mal eine 
CRC-Routine copy&pasted, bei der er stolz die CRC-Tabelle in den 
Funktionsrumpf kopiert hatte... ohne static davor! ;)

Ein anderer (eigentlicher Programmierer) hatte bei einer Funktion einen 
Pointer auf eine lokale Variable der Funktion retourniert...
Gast #4259668
Lesenswert?

Das da mit einem 'alten "Turbo C"-Compiler' funktioniert, wundert mich 
nicht. Mit dem Compiler aus MS VS6 gehts auch noch, mit dem aus VS2005 
(oder wars doch erst VS2008?) geht es nicht mehr, da gibt es dann eine 
'access violation' zur Laufzeit.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren