PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Compiler-Warnungen...



_matze
18.06.2007, 14:51
Hallo!

Ich hab einige Compiler-Warnungen, die ich nicht verstehe (was daran liegen könnte, dass ich C- und AVR-Neuling bin).




eeprom_write_byte(i,cUSART_inp[i]);


Diese Zeile bzw. der Parameter "i" (unsigned short int) erzeugt die folgende Warnung:


../testc.c:72: warning: passing argument 1 of 'eeprom_write_byte' makes pointer from integer without a cast


Was muss ich tun, um die Meldung zu verhindern? Welchen Hintergrund hat das? Eigentlich funktioniert nämlich alles so, wie es soll.

Bei einigen Funktionen (realloc, free, itoa) wird ebenfalls eine Warnung ausgegeben:


../testc.c:66: warning: implicit declaration of function 'realloc'


Wieso implicit declaration?? Die Funktionen laufen ohne Probleme, sind also bekannt. Ich würde die Meldung so verstehen, dass der Funktionsprototyp fehlt. Aber das kann doch nicht sein, oder? Schließlich kommen diese Funktionen ja nicht von mir...

Was muss ich tun, um mein Programm fehler- und warnungsfrei zu kompilieren??

Gruß Matze

CsT
18.06.2007, 15:34
Hi,
bei eeprom_write_byte wird als erster Parameter ein Zeiger auf ein Byte erwartet, du übergibst allerdings den Wert. Deshalb die Warnung.
Für realloc, free und itoa musst du die entsprechenden Headerdateien einbinden. Dies ist hier die stdlib.h, das machst du so: (bis oben im Programm)
#include <stdlib.h>

Viele Grüße
CsT

_matze
18.06.2007, 15:59
Danke, CsT!

Wow, heißt das, dass bislang realloc() und free() gar nicht funktioniert haben??
Das könnte vielleicht erklären, warum das Programm bislang zwar (scheinbar) funktioniert hat, aber nach mehreren Ein- und Ausgaben immer hängenblieb.
Warum lässt der Compiler sowas durchgehen? In dem Fall sollte er doch mit einem "undefined function" oder so abbrechen, oder sehe ich das falsch?

Das erste verstehe ich noch nicht so richtig. Ich bin dank deinem Tipp zu dem Schluss gekommen, dass mein Wert grundsätzlich natürlich genutzt werden kann, jedoch gecastet werden muss. Mit "Zeiger auf Byte" meinst du damit (unsigned char *)i ? Oder liege ich da auch wieder falsch? Zumindest kompiliert er so warnungsfrei.

Gruß Matze

CsT
18.06.2007, 16:43
Richtig, free, realloc usw. sollten bis jetzt nicht richtig funktioniert haben. Der Compiler warnt dich hinreichend, er sieht deine Benutzung quasi als Funktionsdeklaration an. Warnungen sollten nie ignoriert werden ..

Zu 2.
Zeiger übergibt man, indem man ein "&" vor den Variablenname schreibt.
Also: eeprom_write_byte(&i,cUSART_inp[i]);
Möchte jetzt keine weiteren Ausführungen zu Zeigern schreiben .. wenn du nachlesen möchtest: http://www.highscore.de/cpp/einfuehrung/zeiger.html
Mit dem & wird quasi die Adresse der Variablen übergeben.

Grüße
CsT

_matze
18.06.2007, 16:55
Ja, ich weiß schon grundsätzlich, wie Zeiger funktionieren (zumindest grob). Ich habe auch zuerst versucht, die Adresse von i zu übergeben. Dann kam allerdings die folgende Warnung:

../testc.c:75: warning: passing argument 1 of 'eeprom_write_byte' from incompatible pointer type

Richtig scheint zu sein:



eeprom_write_byte((uint8_t*)i,cUSART_inp[i]);


Den Tipp hab ich eben in einem anderen Forum gefunden. Erklären kann ich ihn allerdings nicht, ebensowenig erkenne ich beim kurzen Test einen Unterschied, außer eben, dass die Compiler-Warnung weg ist.

Na ja, jetzt ist Feierabend. Damit kann ich mich morgen weiter rumärgern.

Nochmals VIELEN DANK, CsT!

_matze
19.06.2007, 11:44
Keiner eine Idee, warum bei Funktion eeprom_write_byte() diese cast auf uint8_t* nötig ist? Würde mich sehr interessieren.

Schließlich verstehe ich nicht, warum da ein Pointer übergeben werden soll. Dieser zeigt ja schließlich nicht auf die Adresse im EEPROM, die beschrieben werden soll, sondern nur auf die Adresse von i, in der dann steht, welches Byte (bei mir 0-127) geschrieben werden soll. Und es klappt ja auch mit meiner ursprünglichen Methode ( eeprom_write_byte(i,cUSART_inp[i]) ).

Lasst mich raten! Die Antwort ist: Es ist so, also akzeptiere es!

CsT
19.06.2007, 16:59
Zeiger zu übergeben ist sauberer bei solchen Sachen. Es muss nicht extra eine Kopie angelegt werden, was bei Parameterübergabe by value nötig ist. Hat also programmiertechnisch einige Vorteile, man könnte es auch "normal" mit by value lösen ..
Warum das mit dem & nicht funktioniert frage ich mich .. sollte eigentlich funktionieren.

_matze
22.06.2007, 08:15
../testc.c:75: warning: passing argument 1 of 'eeprom_write_byte' from incompatible pointer type


Das diese Warnung beim Versuch, die Adresse von i zu übergeben, produziert wird, könnte doch daran liegen, dass i unsigned short ist (16 Bit), jedoch ein 8-Bit Pointer erwartet wird. Hatte ja nicht den ganzen Code gepostet, sonst hättet ihr das vielleicht gesehen. Liege ich da richtig?

Ich habe noch ein weiteres interessantes Phänomen:



eeprom_write_byte((uint8_t*)(unsigned int)eeprom_get_next_byte(iEEPROM_lastByte),cUSART_ inp[i]);



/***************/
uint8_t eeprom_get_next_byte(uint8_t iLastByte) {
/***************/
uint8_t iNextByte = iLastByte + 1;
//
if(iNextByte > EEPROM_MAX_BYTE) {
iNextByte = 0;
}
//
iEEPROM_lastByte = iNextByte;
return(iNextByte);
}


Es ist der gleiche Ausdruck, nur das i durch die Funktion eeprom_get_next_byte() ersetzt wurde. Diese liefert uint8_t zurück. Ein Cast nach uint8_t* gibt aber ebenfalls eine Warnung. Es funktioniert nur der Doppel-Cast (uint8_t*)(unsigned int).

Warum muss der 8-Bit-Wert erst in einen 16-Bit-Wert umgewandelt werden, um dann einen Pointer auf einen 8-Bit-Wert zu bekommen?? Ist das nicht unlogisch? Muss ich beim Programm nun darauf achten, dass mindestens ein Byte des SRAM freibleibt, da es während dieser Zeile gebraucht wird? Oder geschieht diese Konvertierung nicht im SRAM?

Bin schon auf eure Antworten gespannt!

Gruß Matze

SprinterSB
22.06.2007, 15:25
eeprom_write_byte((uint8_t*)(unsigned int)eeprom_get_next_byte(iEEPROM_lastByte),cUSART_ inp[i]);


Gruß Matze

Irgendwas stimmt mit deinen Argumenten/Prototypen nicht.

Du liest ein Byte (Datum) und das soll als EEPROM-Adresse interpretiert werden? Dann das:



eeprom_write_byte((void*) eeprom_get_next_byte (iEEPROM_lastByte), cUSART_inp[i]);

_matze
26.06.2007, 08:05
Morgen!

Sorry, dass ich solange nicht gepostet habe.

Deinen Tipp mit dem Cast zum void-pointer habe ich ausprobiert, allerdings kommt dann die folgende Compiler-Warnung:

../testc.c:169: warning: cast to pointer from integer of different size

Am Prototyp sollte es nicht liegen, da die Funktion nicht von mir kommt, sondern in der eeprom.h enthalten ist:




static inline void __attribute__ ((always_inline)) eeprom_write_byte (uint8_t *addr,uint8_t value);


void eeprom_write_byte (uint8_t *addr,uint8_t value)
{
__asm__ __volatile__ (
"mov __tmp_reg__,%1" CR_TAB
XCALL " __eeprom_write_byte_" _REG_LOCATION_SUFFIX
: "+x" (addr)
: "r" (value)
: "memory"
);
}



Wie gesagt, wenn iEEPROM_lastByte eine uint8_t ist, geht der Cast zu uint8_t* nicht bzw. produziert eine Warnung. Bei einer uint16_t geht's, ebenso funktioniert natürlich der Umweg über den zweifachen Cast.

Dass in der Funktion Assembler-Anweisungen verarbeitet werden, kann doch auch nicht der Grund sein, oder? Schließlich meckert der Compiler nur aufgrund des Argumenten-Typs, unabhängig vom Inhalt der Funktion. Richtig?