Forum: Mikrocontroller und Digitale Elektronik "itoa" unklarheit


von Gero N. (geronimo76)


Lesenswert?

Ich benutze bei C18 oft die itoa-funktion (integer to string) um mir 
diverse werte im LCD anzeigen zu lassen ...
Beispiel:
1
LCD_WriteValue(itoa(minuten));

Die entsprechende Funktion sieht so aus:
1
void LCD_WriteValue(unsigned char *pdata)
2
{
3
char n = 0;                    //
4
char temp;                     //
5
while(temp = pdata[n++])       //
6
LCD_WriteChar(temp);            //
7
}

welche wieder in diese Springt:
1
void LCD_set_char(unsigned char chararray[],int len)
2
{
3
int i;
4
i = 0;
5
while(i<len)
6
  {
7
  LCD_WriteChar(chararray[i]);
8
  i++;
9
  }
10
}

Das funktioniert eig. wunderbar, außer, das mir der Compiler diese 
Meldungen bringt:

Warning [2058] call of function without prototype
Warning [2054] suspicious pointer conversion

Einbinden in das project tu ich nur:
#include <delays.h>
#include <string.h>

sobald ich die Lib einbinde, in der ITOA definiert ist, will er, das ich 
das ausgabeformat mit angebe; sprich itoa(intzahl,10) .. 10 = dezimal .. 
aber dann zeigt mein LCD nur noch blödsin an...

jemand ne idee, woher der compiler die itoa nimmt, wenn ich die lib 
nicht einbinde, oder/und warum das einbinden fehlerhafte werte bringt.

von Falk B. (falk)


Lesenswert?

@  Gero Nimo (geronimo76)

>void LCD_WriteValue(unsigned char *pdata)
>{
>char n = 0;                    //
>char temp;                     //
>while(temp = pdata[n++])       //
>LCD_WriteChar(temp);            //
>}

>welche wieder in diese Springt:

>void LCD_set_char(unsigned char chararray[],int len)

Nö,

LCD_WriteChar(temp); ist nicht LCD_set_char

>{
>int i;
>i = 0;
>while(i<len)
>  {
>  LCD_WriteChar(chararray[i]);
>  i++;
>  }
>}

>Warning [2058] call of function without prototype

Dein Funktionsname ist falsch und nirgends in einem Headerfile 
deklariert.

MFG
Falk

von MaWin (Gast)


Lesenswert?

> sobald ich die Lib einbinde, in der ITOA definiert ist, will er, das ich
> das ausgabeformat mit angebe; sprich itoa(intzahl,10) .. 10 = dezimal ..
> aber dann zeigt mein LCD nur noch blödsin an...


Toll, du hast das erste mal erklärt bekommen,
daß itoa
char *itoa(int value, char *string, int radix);
nicht so ist wie du glaubst daß sie ist.
char *itoa(int value);

http://www.mkssoftware.com/docs/man3/itoa.3.asp

und alle deine bisherigen programm grobe Fehler
enthielten (schreibt irgendwo in den Speicher,
mit irgendeinem radix..).

von Gero N. (geronimo76)


Lesenswert?

NIX MEHR VERSTEHT ^^

...wenn ich jetzt nach Schema vorgehe:

#include <stdlib.h>

char *itoa(int value, char *string, int radix);
DESCRIPTION

The itoa() function constructs a string representation of an integer.
PARAMETERS

value

    Is the integer to be converted to string representation.
string

    Points to the buffer that is to hold resulting string. The resulting 
string may be as long as seventeen bytes.
radix

    Is the base of the number; must be in the range 2 - 36.

und entsprechend mein Code ändere ->
char Buffer[20];
itoa( minuten, Buffer,10);
LCD_WriteString(Buffer);

sagt er mir, jetzt sinds zu viele Argumente^^

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:

> sagt er mir, jetzt sinds zu viele Argumente^^


Hast du auch stdlib.h inkludiert?
Welche anderen Header Dateien inkludierst du? Vielleicht haben dir ja 
die Leute von Keil auch noch ein anderes itoa mitgegeben?

Mich macht zb stutzig, dass du einmal itoa klein schreibst, ein anderes 
mal schreibst du es gross.

von Falk B. (falk)


Lesenswert?

Nicht jede itoa kann mit der Radix arbeiten, einige Versionen haben den 
Parameter nicht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hier ist es wichtig, nicht in irgendeiner Headerdatei nachzusehen, 
sondern in der zum Compiler gehörenden. Wie sieht in der der Prototyp 
von itoa aus?

von Gero N. (geronimo76)


Lesenswert?

ich benutze itoa immer klein geschreiben (daran liegts nicht)

wenn ich mir den quelltext der stdlib.h ansehe, dann steht das drin
(stdlib.h nimmt er aus dem INstallationsverzeichniss von C18/h/..)
1
char *itoa (auto int value, auto char *s);
2
/** @name ltoa
3
 * The {\bf ltoa} function converts the {\bf long} value {\bf value} to 
4
 * a radix 10 string representation, storing the resultant string into
5
 * the location pointed to by {\bf s}.
6
 *
7
 * The {\bf ltoa} function is an MPLAB-Cxx extension to the ANSI required
8
 * libraries and may not be present in other implementations.
9
 * @param value value to convert
10
 * @param s pointer to destination string object
11
 * @return The {\bf ltoa} function returns the value of {\bf s}.
12
 */

dort ist es also als 2-argumente angegeben

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann musst Du diese Variante verwenden, denn das ist die zu Deinem 
Compiler gehörende.

Ungewöhnlich, weil vom Standard abweichend.

Um auf Deinen Codeschnippsel zurückzukommen, das muss dann also so 
aussehen:
1
char Buffer[20];
2
itoa(minuten, Buffer);
3
LCD_WriteString(Buffer);

von Gero N. (geronimo76)


Lesenswert?

ich glaub, es liegt an meiner LCD Routine

Warning [2054] suspicious pointer conversion
kommt, wenn ich
LCD_WriteValue(itoa(minuten,10));
aufrufe

WRITEVALUE:
1
void LCD_WriteValue(unsigned char *pdata)
2
  {
3
  //char Buffer[3] = IntWert;
4
  char n = 0;                    //
5
    char temp;                     //
6
    while(temp = pdata[n++])       //
7
    LCD_WriteChar(temp);            //
8
9
  }

..und WRITECHAR
1
void LCD_WriteChar(unsigned char Output)
2
  {
3
  unsigned char x;
4
  x = Output & 0xf0;
5
  LcdBusy();
6
  LcdPort = x;
7
  LcdRs = 1;
8
  LcdE = 1;
9
  Nop();
10
  LcdE = 0;  
11
  x = Output;      
12
  x = (x << 4)& 0xf0;
13
  LcdPort = x;
14
  LcdRs = 1;
15
  LcdE = 1;
16
  Nop();
17
  LcdE = 0;
18
  LcdRs = 0;
19
  }

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:
> ich glaub, es liegt an meiner LCD Routine
>


jetzt bin ich aber enttäuscht

> Warning [2054] suspicious pointer conversion
> kommt, wenn ich
> LCD_WriteValue(itoa(minuten,10));
> aufrufe
>

wie war noch mal dein itoa definiert?

  itoa( zahl, buffer in dem der String abgelegt werden soll)

und wie benutzt du es

  itoa( minuten, 10 )

seit wann ist denn 10 die Adresse eines char-Arrays in das itoa einen 
String ablegen darf?

Du warst so gut unterwegs, wie du dir aus deinem stdlib.h die notwendige 
Information rausgesucht hast. Und dann verwendest du diese Information 
nicht, sondern fängst erst recht wieder mit Raten an.

von holger (Gast)


Lesenswert?

>ich glaub, es liegt an meiner LCD Routine

Nö.

>Warning [2054] suspicious pointer conversion
>kommt, wenn ich
>LCD_WriteValue(itoa(minuten,10));
>aufrufe

Die 10 muss durch einen Zeichenpuffer ersetzr
werden wo dein String auch reinpasst. Radix
kennt dein itoa nicht.

von Loonix (Gast)


Lesenswert?

Gero Nimo schrieb:
> Warning [2054] suspicious pointer conversion

Du übergibst einen char* (oder bei manchen Implementierungen von itoa() 
vielleicht auch einen const char* an eine Funktion, die einen unsigned 
char erwartet. Ich finde das suspicious, der C18 (der übrigens nicht von 
Keil, sondern Microchip kommt @KHB) findet das auch. Zurecht.

von Loonix (Gast)


Lesenswert?

holger schrieb:
> Die 10 muss durch einen Zeichenpuffer ersetzr
> werden wo dein String auch reinpasst. Radix
> kennt dein itoa nicht.

Die Warning[2054] hat er schon im Eröffnungspost.

von Gero N. (geronimo76)


Lesenswert?

tut mir leid, ich bin irgendwie nicht in der lage, auf einen grünen 
zweig zu kommen...

hab jetzt umgeändert in
LCD_WriteValue(itoa(minuten,Buffer));

mit der selben fehlermeldung
wobei ich Buffer vorher als char declariert habe...
char Buffer[10];
oder
char *Buffer[10];
oder auch ohne längenangabe ... erfolglos

von Karl H. (kbuchegg)


Lesenswert?

Loonix schrieb:
> holger schrieb:
>> Die 10 muss durch einen Zeichenpuffer ersetzr
>> werden wo dein String auch reinpasst. Radix
>> kennt dein itoa nicht.
>
> Die Warning[2054] hat er schon im Eröffnungspost.

Aber aus einem anderen Grund. Da hatte er noch keinen Prototypen und 
daher itoa als Funktion angenommen, die einen int liefert.

Die 10 sind trotzdem falsch.

Deine char* / unsigned char* mismatch könnte es tatsächlich sein, aber 
ich denke doch, dass sich der Compiler darüber beschwert, dass man ihm 
einen int anstelle eines Pointers unterjubelt.

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:
> tut mir leid, ich bin irgendwie nicht in der lage, auf einen grünen
> zweig zu kommen...
>
> hab jetzt umgeändert in
> LCD_WriteValue(itoa(minuten,Buffer));
>
> mit der selben fehlermeldung
> wobei ich Buffer vorher als char declariert habe...
> char Buffer[10];
> oder
> char *Buffer[10];
> oder auch ohne längenangabe ... erfolglos

Dann teil das doch mal auf. Du musst das doch nicht so gedrängt 
schreiben.

   char Buffer[10];

   itoa( minuten, Buffer );
   LCD_WriteValue( Buffer );

Bei welcher Zeile gibts die Warning?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Gero Nimo schrieb:
> hab jetzt umgeändert in
> LCD_WriteValue(itoa(minuten,Buffer));

Und wie sieht der Prototyp von LCD_WriteValue aus?
1
void LCD_WriteValue(unsigned char *pdata)

Du übergibst hier einen char*, keinen unsigned char*.

Das ist der Grund für die Warnung, nicht die Deklaration von Buffer.

Es ist in solchen Problemfällen immer sinnvoll, nur ein Statement pro 
Quelltextzeile zu haben und nicht mehrere zu schachteln.

Statt
1
LCD_WriteValue(itoa(minuten,Buffer));
solltest Du schreiben
1
itoa(minuten,Buffer);
2
LCD_WriteValue(Buffer);
Dann hättest Du klar gesehen, woher die Warnung kommt.

> wobei ich Buffer vorher als char declariert habe...
> oder
> char *Buffer[10];
> oder auch ohne längenangabe ...

Die beiden letzten Varianten sind natürlich vollkommen falsch.

von holger (Gast)


Lesenswert?

Nimm den Code von Rufus

Beitrag "Re: "itoa" unklarheit"

von Gero N. (geronimo76)


Lesenswert?

das witzige ist ja, das sobald ich die stdlib.h raus schmeiße, itoa ohne 
alles benutze (lcd_writeValue(itoa(intzahl)); alles funktioniert ... 
richtig im LCD angezeigt wird ... mich haben nur die vielen Warnings 
gestört, beim compilieren^^

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:
> das witzige ist ja, das sobald ich die stdlib.h raus schmeiße,

das ist das Blödeste was du tun kannst.

So eine Warnung:
1
Warning [2058] call of function without prototype
solltest du immer als Fehler ansehen und beheben.

Wenn sie kommt, dann muss der Compiler Standardannahmen treffen. Wenn 
die passen, dann hast du Glück gehabt. Aber wehe wenn sie nicht passen! 
(UNd bei dir haben sie nicht gepasst)

 itoa ohne
> alles benutze (lcd_writeValue(itoa(intzahl)); alles funktioniert ...

scheinbar.
In Wirklichkeit hattest du einen enormen Bock geschossen, den du bisher 
nur noch nicht bemerkt hast. Aber auch ein Fehler, den man noch nicht 
entdeckt hat, ist und bleibt ein Fehler.
Üblicherweise wartet der solange zu, bis er maximalen Schaden anrichten 
kann und schlägt dann erbarmungslos zu. Zb wenn du das Programm das 
erste mal dem Kunden vorführst :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Gero Nimo schrieb:
> das witzige ist ja, das sobald ich die stdlib.h raus schmeiße, itoa ohne
> alles benutze (lcd_writeValue(itoa(intzahl)); alles funktioniert ...

Das ist eher ein sehr großer Zufall. itoa erwartet zwei Argumente, Du 
übergibst nur eines. Das zweite Argument ist also was, was eher 
zufälligerweise auf dem Stack steht. Sofern das eine RAM-Adresse ist, 
kann itoa dort hineinschreiben und diese Adresse zurückgeben, auf daß 
sie Deiner LCD_WriteValue-Funktion übergeben wird.

Mit anderen Worten: Das ist Pfusch der ganz üblen Art.

von Gero N. (geronimo76)


Lesenswert?

wir sind noch nicht fertig^^ ... Code geändert in:
1
itoa(minuten,Buffer);
2
LCD_WriteValue(Buffer)

Ergebiss:

Warning [2054] suspicious pointer conversion

liegts wohl doch an meinen LCD routinen

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ja, und? Woher das kommt HABE ICH DIR BEREITS GESCHRIEBEN!

Wie ist Buffer deklariert? Was erwartet Deine LCD_WriteValue-Funktion?

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:
> wir sind noch nicht fertig^^ ... Code geändert in:
>
>
1
> itoa(minuten,Buffer);
2
> LCD_WriteValue(Buffer)
3
>
>
> Ergebiss:
>
> Warning [2054] suspicious pointer conversion

bei welcher Zeile?

Sinn der Übung war es ja, herauszufinden, worin genau die Warnung 
begründet ist. Also wurde deine ultrakompakte Lösung in 2 Teile zerlegt, 
damit man weiter eingrenzen kann.

(Aber jetzt kann es nur noch der  char*/unsiged char* mismatch sein)

von Gero N. (geronimo76)


Lesenswert?

Also .. meine LCD Routinen sehen so aus
1
/** I N C L U D E S **********************************************************/
2
#include <p18cxxx.h>
3
#include <delays.h>
4
#include <string.h>
5
#include "MyLCD4.h"
6
7
/* */
8
#define  LcdE        PORTDbits.RD0    
9
#define  LcdRw        PORTDbits.RD1    
10
#define  LcdRs        PORTDbits.RD2    
11
#define LcdPort        PORTD
12
#define TRIS_LCD        TRISD
13
14
#define Zeile1        0x80
15
#define Zeile2        0xC0
16
#define Zeile3        0x94
17
#define Zeile4        0xD4
18
19
#define Zeile1_start    0x80
20
#define Zeile2_start    0xC0
21
#define Zeile3_start    0x94
22
#define Zeile4_start    0xD4
23
24
#define Zeile1_menu      0x8D
25
#define Zeile2_menu      0xCD
26
#define Zeile3_menu      0xA1
27
#define Zeile4_menu      0xE1
28
29
/* */
30
31
#pragma code
32
33
unsigned char LcdStatus;
34
unsigned char LcdDaten;
35
36
void SET_DD_ADDR(unsigned char addr)
37
  {
38
  unsigned char uebergabe;
39
  LcdRs = 0;                //bcf  LcdRs     ; INSTR REG
40
  LcdRw = 0;                //bcf  LcdRw    ; WRITE
41
  uebergabe = addr & 0b01111111;      //ANDLW  B'01111111'  ; DDRAM CHOPOFF
42
  uebergabe = uebergabe | 0b10000000;    //IORLW  B'10000000'   ; DDRAM AREA
43
  OutLcdControl(uebergabe);
44
  }
45
46
void SET_CG_ADDR(unsigned char addr)
47
  {
48
  unsigned char uebergabe;
49
  LcdRs = 0;                //bcf  LcdRs     ; INSTR REG
50
  LcdRw = 0;                //bcf  LcdRw    ; WRITE
51
  uebergabe = addr & 0b00111111;      //ANDLW  B'01111111'  ; DDRAM CHOPOFF
52
  uebergabe = uebergabe | 0b01000000;    //IORLW  B'10000000'   ; DDRAM AREA
53
  OutLcdControl(uebergabe);
54
  }
55
56
void LcdBusy(void)
57
  {
58
  Delay1KTCYx(10);    //2ms
59
  
60
    TRIS_LCD = 0b11110000;  //TRISB || 0b11110000;
61
62
  while(LcdStatus,7 == 1)
63
    {    
64
    LcdRs = 0;
65
    LcdRw = 1;
66
    LcdE = 1;
67
    Nop();
68
    LcdPort = 0b11110000;
69
    LcdStatus = LcdPort;
70
    LcdE = 0;
71
    Nop();
72
    LcdE = 1;
73
    Nop();
74
    LcdE = 0;
75
    }
76
  LcdRw = 0;
77
  TRIS_LCD = TRIS_LCD & 0b00001111;
78
  
79
  }
80
  
81
void OutLcdControl(unsigned char ControlData)
82
  {
83
  unsigned char x;
84
  x = ControlData;
85
  LcdBusy();
86
  LcdDaten = ControlData;
87
  x = x & 0xf0;
88
  LcdPort = x;
89
  LcdE = 1;
90
  Nop();
91
  LcdE = 0;
92
93
  x = ControlData;      
94
  x = (x << 4)& 0xf0;
95
  LcdPort = x;
96
  LcdE = 1;
97
  Nop();
98
  LcdE = 0;
99
100
  }
101
102
void LCD_WriteString( static const rom char *string)
103
  {
104
  while(*string) {LCD_WriteChar(*string++);}
105
  }
106
107
void LCD_WriteValue(unsigned char *pdata)
108
  {
109
  //char Buffer[3] = IntWert;
110
  char n = 0;                    //
111
    char temp;                     //
112
    while(temp = pdata[n++])       //
113
    LCD_WriteChar(temp);            //
114
115
  }
116
117
void LCD_set_char(unsigned char chararray[],int len)
118
  {
119
  int i;
120
  SET_CG_ADDR(0b00000000);
121
  i = 0;
122
  while(i<len)
123
    {
124
    LCD_WriteChar(chararray[i]);
125
    i++;
126
    }
127
  SET_DD_ADDR(0b00000000);
128
  }
129
130
void LCD_WriteChar(unsigned char Output)
131
  {
132
  unsigned char x;
133
  x = Output & 0xf0;
134
  LcdBusy();
135
  LcdPort = x;
136
  LcdRs = 1;
137
  LcdE = 1;
138
  Nop();
139
  LcdE = 0;  
140
  x = Output;      
141
  x = (x << 4)& 0xf0;
142
  LcdPort = x;
143
  LcdRs = 1;
144
  LcdE = 1;
145
  Nop();
146
  LcdE = 0;
147
  LcdRs = 0;
148
  }
149
150
void Control8Bit(unsigned char ControlBit)
151
  {
152
  LcdPort = ControlBit;
153
  LcdE = 1;
154
  Nop();
155
  LcdE = 0;
156
  Delay1KTCYx(50);
157
158
  }
159
160
161
  
162
void LCD_INIT(void)
163
  {
164
  Delay10KTCYx(250);
165
  LcdPort = 0b00110000;
166
  LcdE = 1;
167
  Nop();  
168
  LcdE = 0;
169
  Delay1KTCYx(250);
170
  Control8Bit(0b00110000);
171
  Control8Bit(0b00110000);
172
  Control8Bit(0b00100000);
173
  OutLcdControl(0b00000001);
174
  OutLcdControl(0b00101000);
175
  OutLcdControl(0b00001000);
176
  OutLcdControl(0b00000110);
177
  OutLcdControl(0b00000011);
178
  OutLcdControl(0b00001100);
179
  }

Will ich text ausgeben, dann:
LCD_WriteString("Mein Text");
Bei berechneten zahlen nahm ich immer :
LCD_WriteValue(itoa(intzahl));

WriteString: void LCD_WriteString(static const rom char *string);
WriteValue: void LCD_WriteValue(unsigned char *pdata);

itoa(minuten,Buffer);
LCD_WriteValue(Buffer); => Warning [2054] suspicious pointer conversion

ODER
itoa(minuten,Buffer);
LCD_WriteString(Buffer); => Warning [2066] type qualifier mismatch in 
assignment

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Lies doch einfach mal, was man Dir hier hinschreibt!


> void LCD_WriteValue(unsigned char *pdata);

Da steht unsigned char*

Und, wie ist Buffer deklariert?

von Gero N. (geronimo76)


Lesenswert?

hab ich gelesen und geändert, leider mit gleichbleibender Fehlermeldung 
beim itoa aufruf

Warning [2054] suspicious pointer conversion

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:
> hab ich gelesen und geändert, leider mit gleichbleibender Fehlermeldung
> beim itoa aufruf
>
> Warning [2054] suspicious pointer conversion

Und, was sagt dir das jetzt?

auf der einen Seite bräuchtest du für itoa ein char Array
Und auf der anderen Seite bräuchtest du für LCD_WriteValue ein unsigned 
char Array.

Ein Array kann aber nicht beides gleichzeitig sein. Es kann nicht 
gleichzeitig nur char und trotzdem unsigned char sein.

Was ist deine Schlussfolgerung?

von Gero N. (geronimo76)


Lesenswert?

BINGO

hab jetzt meine LCD Routine abgeändert ... danke für eure hilfe, war 
schon am verzweifeln ^^

von Karl H. (kbuchegg)


Lesenswert?

Na siehste.
Und beim nächsten mal kennst du die Fehlermeldung bereits und weißt, 
worauf du achten musst.
Datentypen müssen übereinstimmen. Tun sie das nicht, dann kann das ein 
Hinweis auf einen systematischen Fehler sein.

Ist wie in der Physik. Wenn man eine Geschweindigkeit berechnet, indem 
man Körpermasse durch Wegstrecke dividiert, dann kann da was nicht 
stimmen.
Körpermasse hat als Einheit kg, Wegstrecke hat als Einheit meter. 
Berechnet wird also kg / meter. Eine Geschwindigkeit hat aber die 
Einheit meter / sekunde. Also kann bei dieser Berechnung der 
"Geschwindigkeit" schon mal etwas nicht stimmen.

  meter / sekunde   =  kg / meter

das passt hinten und vorne nicht. Da steht links vom = und rechts davon 
völlig andere Einheiten. Was auch immer da berechnet wird, es kann 
keine Geschwindigkeit sein.

Und deine 'Einheiten' sind in der Programmierung eben die Datentypen von 
Variablen. Wenn die nicht zusammenpassen, dann kann das ein Hinweis auf 
ein verstecktes Problem sein. Und deshalb warnt dich der Compiler.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.