C: Int to String Funktion schlägt fehl.

Gast #1117471
Lesenswert?

Hallo,

ich habe mir aus dem Artikel:
http://www.mikrocontroller.net/articles/Festkommaarithmetik

Die Funktion: void my_uitoa(uint32_t zahl, char* string)
abgeschaut.

Mein Programm sieht so aus:
1
#include "asuro.h"
2

3
void my_uitoa(unsigned int zahl, unsigned char* char_p, unsigned char start) {
4
  char i;                             // schleifenzähler
5
  
6
  for(i=start; i>=(start-3); i--) {
7
    char_p[i]=(zahl % 10) +'0';         // Modulo rechnen, dann den ASCII-Code von '0' addieren
8
    zahl /= 10;
9
  }
10
}
11

12
int main (void){
13
//                           0   1   2   3
14
 unsigned char char_a[4] = {'1','0','2','3'}; 
15
 unsigned int test_int = 3201;
16
 while (1){
17
     my_uitoa(test_int,char_a,3);
18
     SerWrite(char_a, 4);
19
     // Deklaration von SerWrite(unsigned char* char_p, unsigned char byte_cnt); 
20
 }
21
 return 0;
22
}

Aber leider tut das Programm nicht was es soll! Bzw. es tut gar nix, ich 
habe versucht hinter dem Funktionsaufruf eine LED zu schalten, so weit 
kommt er schon nicht mehr.

Benutze ich SerWrite ohne Aufruf von my_uitoa funktioniert die Ausgabe.. 
also muss der Fehler irgendwo in der Funktion my_uitoa oder im Auruf 
liegen.. aber ich habe gerade Tomaten auf den Augen und finde den Fehler 
nicht..

hab auch schon den Start parameter weggelassen... der soll später (wenns 
mal funktioniert) dazu dienen an verschiedene Stellen in einem string zu 
schreiben..

Achja und den /0 Terminator im String brauche ich auch nicht.. wie 
gesagt funktioniert der Aufruf von SerWrite ohne my_uitoa...

VIELEN DANK!!
Gast #1117487
Lesenswert?

kopf kratz

Den Hinweis versteh ich gerade nicht...
Der Schleifenzähler sollte ja auf jeden fall signed sein.. sonst bricht 
die schleife ja nie ab.

Wo habe ich einen signed/unsigned Fehler ???

DANKE !!!
#1117488
Lesenswert?

Du übergibst der Funktion einen Zeiger (unsigned char* char_p), 
versuchst in der Funktion aber, diesen als Array zu bearbeiten 
(char_p[i]=(zahl % 10) +'0';). Du musst da schon den Zeiger 
dereferenzieren.

Abgesehen davon solltest Du Dir direkt angewöhnen, ASCII-Strings in C 
auch zu terminieren, da Du sonst irgendwann mal Probleme bekommen wirst, 
wenn Du Bibliotheksfunktionen zur Stringverarbeitung bzw. Stringausgabe 
verwenden willst, die alle mit nullterminierten Strings arbeiten.
#1117491
Lesenswert?

> unsigned char char_a[4] = {'1','0','2','3'};
Das sollte man übrigens auch nicht machen. ASCII-Zeichen (Textzeichen) 
sind in C grundsätzlich vom Typ char und nicht unsigned char. Auch, 
wenn es jetzt nur für Deine eigenen Anwendungsfälle ist, gewöhne es Dir 
aus o.g. Gründen gleich richtig an.
Gast #1117495
Lesenswert?

noch mehr am kopf kratz

unsigned char* char_p

ist doch ein Pointer auf (unsigned char) ? Ja, oder net?

und mit char_p[i] wird der Zeiger doch dereferenziert ???
(adresse = &(char_p[0]) + (i * sizeof(unsigned char))  verwirrt bin

Oder habe ich da nen grundsätzlichen Denkfehler drin ???
#1117496
Lesenswert?

Johannes M. wrote:
> Du übergibst der Funktion einen Zeiger (unsigned char* char_p),
> versuchst in der Funktion aber, diesen als Array zu bearbeiten
> (char_p[i]=(zahl % 10) +'0';). Du musst da schon den Zeiger
> dereferenzieren.

Er dereferenziert ihn doch mit "[]". Das ist völlig ok so.
#1117497
Lesenswert?

Johannes M. wrote:
> Du übergibst der Funktion einen Zeiger (unsigned char* char_p),
> versuchst in der Funktion aber, diesen als Array zu bearbeiten
> (char_p[i]=(zahl % 10) +'0';). Du musst da schon den Zeiger
> dereferenzieren.

Nein, muss man nicht. Das funktioniert auch so.


Ich würde anstelle von
 char i;
besser
signed char i;
schreiben, denn char ist nicht immer als signed definiert, das hängt 
etwas von den Compilereinstellungen ab. Und wenn start dann <3 ist, dann 
kann es sein, dass die Schleife ewig läuft.
Moderator (Firma: Titel) Persönliche Seite #1117499
Lesenswert?

>   for(i=start; i>=(start-3); i--) {
Es ist schlecht, den Compiler entscheiden zu lassen, welche Datentypen 
er nehmen darf.
Was kommt das wohl raus?
 ... i>=(start-3) ...   --> ein Vergleich signed mit unsigned

Ich würde den wenigstens Casten, dass der Compiler nicht beliebig 
kreativ sein kann:

   for(i=start; i>=((char)start-3); i--) {


Oder gib deiner Funktion als Parameter einfach mal
     my_uitoa(test_int,char_a, 2 );
Was passiert jetzt?
#1117500
Lesenswert?

high-side wrote:

> Wo habe ich einen signed/unsigned Fehler ???

Hier:
1
  char i;                             // schleifenzähler
2
  
3
  for(i=start; i>=(start-3); i--) {

Ob ein char signed oder unsigned ist, liegt im Ermessen des Compilers. 
Bei unsigned kann die Schleife aber ganz schnell zur Endlosschleife 
werden (z.B. bei deinem start=3).
Also:
char i;
->
signed char i;
Gast #1117501
Lesenswert?

Du hast schon Recht, dass ich mit Strings anders umgehen sollte... aber 
der Code sollte doch trotzdem funktionieren ???

ich will ja nur bytes übertragen.. wie gesagt erwartet die 
Übertragungsfunktion SerWrite keinen terminierten String sondern einfach 
Bytes... aber soweit kommt er ja leider gar net.... :-(
Gast #1117506
Lesenswert?

@Stefan:

Hier:
1
  char i;                             // schleifenzähler
2
  
3
  for(i=start; i>=(start-3); i--) {


Du meinst ich muss hier explizit signed angeben ??? ich dachte char wäre 
von natur aus schon ein vorzeichenbehafteter Wert ???

Der Controller ist ein ATMEGA8 ...
Gast #1117507
Lesenswert?

Hallo,

ich denke, dass das Problem in der Abbruchbedingung liegt. Hier wird 
unsigned char mit signed char verglichen, was im Falle 3 dazu führt, 
dass unsigned char immer größer gleich 0 und damit immer wahr ist.

Gruß
Torsten
Gast #1117513
Lesenswert?

@lothar:

ich werde das mit 2 und dem cast mal ausprobieren...

jetzt bin ich aber mal gespannt....

dachte das "char i" hier schon die größte Stolperfalle gewesen wäre ;-) 
... über die ich auch schon gestoplert bin.. dann dachte ich JA das 
wars! Wars aber leider anscheinend doch nicht.... :-(

Danke an alle!


8 Bit können so gemein sein... ;-)
#1117543
Lesenswert?

Lothar Miller wrote:
>> ich werde das mit 2 und dem cast mal ausprobieren...
> Wenn du das machst gibt es einen amoklaufenden Pointer (wg. Index = -1).
> Nein, du solltest das nur Durchdenken.

Oder was in die gleiche Kerbe schlägt
1
    for(i=start; i>=(start-3); i--) {

Huch, wieso 3? Wo kommen diese 3 her? Was bedeuten sie?
Warum nicht 4 oder 5? Welche Implikationen hat das für die
möglichen Werte in start?

und denk drann:
Wenn in einem Ausdruck sowohl signed als auch unsigned Werte vorkommen, 
wird alles nach unsigned gewandelt!

  i ist bei dir signed
  start ist unsigned

-> Für den Vergleich wird alles nach unsigned gewandelt.

Aber: Als unsigned ausgedrückt, kann i nie den Wert -1 haben!
Der wär aber nötig, wenn start den Wert 3 hat, denn 3 - 3 macht 0
und damit die Schleife abbrechen kann muss i kleiner als 0 werden.
i wird zwar kleiner als 0, aber nicht während des Vergleichs. Während 
des Vergleichs wird i als unsigned Wert angesehen und als unsigned 
gesehen kann i per Definition nicht negativ werden.

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