Hallo,
ich habe gerade in meinen K&R hineingebissen, wg.
folgendem Problem:
MSP430- CCS 6.0 - TI - c-compiler
Democode vom Distri weiterverbastelt:
Für ein GLCD wird eine Laufschrift angezeigt (funktioniert!)
Es gibt Texte, die einfach im Quellcode mitgegeben werden
und es gibt constant-Texte im Flash (das soll einmal ein Menue werden).
1
constchartext[]="Das ist ein wenig Text im Flash";
scroll_left(text,2,2,2,10);// text aus dem Flash - s.o.
und strlength:
1
charstrlength(char*string)
2
{
3
char*p=string;
4
while(*p!=(0x00)){p++;};
5
6
returnp-string;
7
}
Problem = 2 Warnungen:
Der compiler meckert natürlich an, das das 'constant char'
von *string nicht dem Wert '*string' für strlength entspricht.
#169-D argument of type "const char *" is incompatible with parameter of
type "char *"
und meint dann zu dem 'x'
#552-D variable "x" was set but never used
Wie gesagt, es funktioniert trotzdem (auch der Rückgabewert passt)!!??
Da ich aber keine Warnungen mag und auch ganz gerne verstehe, was da
passiert:
Wenn ich in der Funktion 'strlength' sowohl Daten aus dem Flash,
als auch aus dem RAM verarbeiten möchte, kann man das in einer Funktion?
Besten Dank!
Dietmar
Da die MSP eine von Neumann Architektur haben, düfte es eigentlich
keinen Unterschied machen, ob der COmpiler die Texte ins Flash oder ins
RAM legt. In beiden Fällen sind die Zugriffe (wegen van Neumann) gleich.
Zu deiner Frage.
Ein const in einer Argumentliste einer Funktion kann gelesen werden als
die Zusicherung der Funktion, den WErt nicht zu verändern. D.h. die
Funktion gibt damit an den Aufrufer eine Garantie
1
voidfoo(constchar*arg)
2
{
3
...
4
}
ist also die Zusicherung der Funktion, dass sie nicht versuchen wird,
die char auf die der Pointer zeigt zu verändern. Wenn im Code das
trotzdem versucht wird
1
voidfoo(constchar*arg)
2
{
3
*arg='a';
4
}
dann fliegt dem Programmierer dieser Funktion eine Fehlermeldung um die
Ohren. Denn dann hält sich der Code nicht an diese Zusicherung.
Warum ist das wichtig.
Nun. Wenn der Aufrufer einen Text hat, so wie hier
1
constchartxt[]="Hallo";
2
3
foo(txt);
dann muss er sich darauf verlassen können, dass nach Rückkeehr von der
Funktion der Text immer noch so ist, wie er vorher war. SChliesslich hat
er ihn ja auch deshalb als 'const' markiert, damit ihn der Compiler
daran hindert, den Text zu verändern. Was für ihn gilt, muss daher auch
für die Funktion gelten: die Funktion muss die Zusicherung abgeben,
nicht zu versuchen den Text zu ändern. Genau das macht sie aber mit dem
const in
1
voidfoo(constchar*arg);
Es gibt noch einen anderen Fall
1
...
2
foo("text");
String Literale sind per Definition unveränderbar. D.h. auch hier muss
die Funktion diese Zusicherung abgeben.
Ist logisch. strlength() hat nicht das const Schlüsselwort. Der Compiler
geht daher davon aus, dass strlength() die variable eventuell verändert.
Ob sie es das wirklich macht, ist derm Compiler egal, das prüft er
nicht.
scroll_left() hat das const Schlüsselwort. Sie verspricht dem Compiler,
dass die Variable nicht verändert wird. Aber sie ruft strlength() auf,
welche das nicht mehr verspricht. Diesen Konflikt meldet der Compiler
als Warnung.
Wenn du der Variable x nur einen Wert zuweist, den aber nirgends
verwendest (ausliest), dann ist die Warnung völlig korrekt. Je nach
Optimizer Einstellung fürht dies dazu, dass die Variable x im Binärcode
gar nicht existiert. Leider hast Du den wirklich wichtigen Part des
Quelltextes ausgelassen.
Besten Dank, die Herren!
@Karl Heinz:
Das war mir klar und es findet sich im Sinn auch
im K&R und im 'C von A bis Z'- was immer man auch davon halten mag.
Aber schön erklärt, wie immer.
@stefanus:
o.k.- was willst Du wissen ?? kleiner Scherz.
'x' taucht wirklich nicht mehr auf in 'scroll_left'.
Da hat der compiler Recht.
Nur- der Rückgabewert stimmt trotzdem !!??
Ich habe extra die Texte variiert, damit das kein Zufall
beim Debuggen ist.
Meine Frage war, wie ich strlength() dazu bekomme (evtl.),
char* und constant char* zu verarbeiten.
Dietmar Sch. schrieb:> @Karl Heinz:> Das war mir klar und es findet sich im Sinn auch
...
> Meine Frage war, wie ich strlength() dazu bekomme (evtl.),> char* und constant char* zu verarbeiten.
Jetzt muss ich mich aber wundern
Welchen Teil der Ausführungen hast du nicht verstanden, warum du in
eine const Warnung kriegst? Wenn scroll_left an seinen Aufrufer die
Zusicherung const char* macht, dann kann es nicht FUnktionen aufrufen,
die potentiell in der Lage wären (wegen der fehlenden const Zusicherung)
die Zeichen zu verändern.
Und noch viel schlimmer: Welchen Teil hast du nichtg verstanden, warum
eine Modifikation der Funktion strlength auf
1
charstrlength(constchar*string)
2
/* ***** */
3
{
4
char*p=string;
5
while(*p!=(0x00)){p++;};
6
7
returnp-string;
8
}
die 1. Warnung beseitigen würde?
Zur 2. Warnung sag ich mal nichts weiter. Die wird dir doch nicht
wirklich ein "Problem" bereiten.
Dietmar Sch. schrieb:> Meine Frage war, wie ich strlength() dazu bekomme (evtl.),> char* und constant char* zu verarbeiten.
Indem Du es mit einem const-Pointer deklarierst.
Einer Funktion, die const char* erwartet, darf man auch char* übergeben.
Andersrum darf ein const char* nicht an eine Funktion übergeben werden,
die char* erwartet.
Wo liegt der Reiz, eine eigene Stringlängenfunktion zu schreiben? Warum
verwendest Du nicht einfach strlen?
Rufus Τ. Firefly schrieb:> Wo liegt der Reiz, eine eigene Stringlängenfunktion zu schreiben? Warum> verwendest Du nicht einfach strlen?
... die – ganz nebenbei bemerkt – ein "const" in ihrer Deklaration
stehen hat
1
size_tstrlen(constchar*s);
und trotzdem ohne Warnungen auch für Nicht-Const-Strings anwendbar ist
;-)
Rufus Τ. Firefly schrieb:> Einer Funktion, die const char* erwartet, darf man auch char* übergeben.
Wenn ich da anhängen darf. Vielleicht hat er ja den Teil nicht
verstanden.
Genau deshalb bin ich ja auf der "Zusicherung" so rumgeritten!
Wenn ich 2 Bücher habe, eine original Gutenberg-Bibel und "Die kleine
Raupe Nimmersatt", dann kannst du die dir bei mir ausleihen.#
Gibst du mit die Zusicherung nichts in die Bücher hineinzuschreiben,
dann kannst du von mir sowohl die Gutenberg-Bibel haben als auch die
Raupe Nimmersatt. Persönlich wär mir das egal, ob du etwas in die "Raupe
Nimmersatt" hineinschreibst oder nicht, aber wenn du mir zusicherst, das
nicht zu tun, ist es auch gut. Selbst dann, wenn ich in dem Fall nicht
auf dieser Zusicherung bestehe.
Aber bei der Gutenberg Bibel ist mir das nicht egal. Da WILL ich von dir
diese Zusicherung haben.
Gibst du mir die Zusicherung nicht, dann kriegst du von mir nur die
Raupe Nimmersatt. Gibst du mir aber die Zusicherung, dann kannst du
beides von mir haben.
PAH! - wenn K&R das dürfen (section 5.4 page 103),
dann darf ich das auch!
;-)
Ne- das war so vorgegeben, vom Beispielcode, wie
eingangs erwähnt.
@Karl Heinz:
Ganz einfach ein Brett vor dem Kopf! Und dann noch ein altes.
Rufus hat es gelockert:
>Einer Funktion, die const char* erwartet, darf man auch char* übergeben.
Geändert-läuft PROBLEM SOLVED!
Besten Dank und Schönen Feierabend!
Dietmar Sch. schrieb:> Ich würde nie in irgendeinem geliehenen Buch herumkritzeln!> Von daher 'immer' const char*'.> ;-)
Jetzt verstehen wir uns.
:-)
Ein 'const char*' sollte daher in einer Funktions-Argumentliste
eigentlich der Normalfall sein. Und nur dann, wenn die Funktion
tatsächlich den Text ändern muss, dann und nur dann kommt das const weg.
Karl Heinz schrieb:> Wenn ich 2 Bücher habe, eine original Gutenberg-Bibel und "Die kleine> Raupe Nimmersatt"
Damit wäre auch geklärt, mit welchen Büchern du so gut programmieren
gelernt hast und wie dein Tipp an jeden Programmieranfänger "Kauf dir
ein Buch!" zu verstehen ist ;-)