PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C Frust der Woche "strcpy"



wkrug
19.01.2019, 07:40
Mal kein Problem, das gelöst werden muß, aber eines das mich gestern 4 Stunden gekostet hat.
Ich progge schon seit einiger Zeit mit ATMEL Studio 7 in C herum.
Gestern wollte ich einen String in einen anderen mit strcpy reinkopieren und das wollte nicht funktionieren.




#include <string.h>
....

int main(void)
{
uint8_t zeile[20];
.....
.....
strcpy(zeile,"Hallo Welt\0");
}

Das wurde mit einer Fehlermeldung:

Warning pointer targets in passing argument 1 of 'strcpy' differ in signedness [-Wpointer-sign]

quittiert

Dann begann die Suche im Internet - Sieht alles ähnlich aus!
In der AVR Studio Hilfe stand dann, das die Funktion strcpy einen Pointer zurückliefert.
Auch Versuche in diese Richtung - kein Erfolg.

Erst als Ich die Variablendefinition auf char zeile[20]; umgestellt hatte funktionierte alles wie gewünscht.

Ich finde, das ist ein blöder Fehler und die Compiler Aussage hilft hier auch nicht wirklich weiter.
Ein char ist ja eigentlich im Prinzip das gleiche wie ein uint8_t.
Übrigens einen unsigned char mag der Compiler auch nicht! Und spuckt die selbe Fehlermeldung aus.

Eventuell hat ja mal wer das gleiche Problem.

oberallgeier
19.01.2019, 08:24
.. Ein char ist ja eigentlich im Prinzip das gleiche wie ein uint8_t .. Eventuell hat ja mal wer das gleiche Problem.Stimmt, jetzt, da ich das lese - darüber bin ich auch schon gestolpert - und wohl auch in Studio7. Im Studio4 läuft fast alles das ich code. ICH hatte das damals auf meine äusserst dünnen Kenntnisse der Sprache C zurückgeführt. Übrigens hatte ich ähnliche Probleme mit einer Definitionsbibliothek (Peter Dannegger, "mydefs.h"), soweit ich mich erinnern kann damit:

typedef unsigned char u8;
..
typedef uint16_t u16; //typedef unsigned short u16;
typedef int16_t s16; //typedef signed short s16;

HaWe
19.01.2019, 09:31
http://www.cplusplus.com/reference/cstring/strcpy/


function
<cstring>
strcpy

char * strcpy ( char * destination, const char * source );

Copy string
Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).

(...)

Die Definition verlangt also char*.

so klappt es bei mir immer, sowohl per gpp auf Arduino als auch gcc und gpp auf Raspberry Pi /Linux und Borland C++ und devcpp auf Windows PC

PS
char ist auf 8-bit AVRs ein signed char, nur auf 32bit-cpus ist char unsigned, hat also auch keine über alle Plattformen hinweg fest definierte Bedeutung 8)
Da avr-gcc aber da etwas eigen ist in Bezug auf stdint.h und string.h (Arduino g++ ebenfalls), ist man da in Beug auf strcpy etc. ziemlich auf char eingeschränkt.
u.U. (pure Spekulation) hilft der Compilerschalter -fpermissive, um außer char auch die stdint-Typen zu erlauben, ist aber sicher ebenfalls Compiler- und Plattform-abhängig.



-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will allow some nonconforming code to compile.

Bottom line: don't use it unless you know what you are doing!

Klebwax
19.01.2019, 17:05
Mal kein Problem, das gelöst werden muß, aber eines das mich gestern 4 Stunden gekostet hat.
Ich progge schon seit einiger Zeit mit ATMEL Studio 7 in C herum.
Gestern wollte ich einen String in einen anderen mit strcpy reinkopieren und das wollte nicht funktionieren.
.......

Warning pointer targets in passing argument 1 of 'strcpy' differ in signedness [-Wpointer-sign]
....

Ein char ist ja eigentlich im Prinzip das gleiche wie ein uint8_t.
Übrigens einen unsigned char mag der Compiler auch nicht! Und spuckt die selbe Fehlermeldung aus.

Mal davon abgesehen, daß "Warning" kein Fehler ist, lernt man daraus follgendes: die Funktionen der libc, die mit str anfangen, behandeln Strings, Zeichenketten. Diese bestehen in C aus chars, Buchstaben. Wenn man Arrays von uint8_t kopieren will, benutzt man mencpy().

Man hätte da auch nicht lange suchen müssen. Wie strcpy() definiert ist, steht in string.h. Daher (und nur daher) weiß das auch der Compiler. Typischerweise kann man sich das auch mit der IDE anzeigen lassen. Da steht, der Typ des ersten Parameter ist char*. Und der Compiler hat richtig bemerkt, bei zeile steht uint8_t *, also etwas anderes. Die Stringlibray ist für den Compiler genauso unbekannt, wie von dir geschriebener Code.

Man könnte das Problem umgehen, wenn man in string.h statt char * uint8_t * schreiben würde. Damit wäre dann natürlich jeder andere Code, der strcpy() benutzt kaputt.

Ein char ist etwas anderes, als uint8_t. In anderen, moderneren Sprachen werden Zeichen als Unicode dargestellt. Und das sind keine 8 Bit. Es schadet also nicht, sich auch in C daran zu gewöhnen, etwas pingeliger zu sein, wenn es um Strings geht.

Übrigens, der Compiler und die libc sind unterschiedliche Dinge. Der gcc ist immer der gcc und benimmt sich gleich. Die unterstützenden Libraries, zum Beispiel für Integer oder Long-Integer Mathematik etc. sind natürlich CPU-abhängig und damit unterschiedlich.

MfG Klebwax

HaWe
19.01.2019, 19:02
Man könnte das Problem umgehen, wenn man in string.h statt char * uint8_t * schreiben würde.
Ein char ist etwas anderes, als uint8_t.

Nein, anders herum!
Man könnte das Problem umgehen, wenn man für einen ctring (string.h) für einen AVR (!)
statt char *
int8_t *
schreiben würde,
denn char ist auf AVRs signed, wie ich bereits schrieb!

wkrug
19.01.2019, 19:26
Alles schön und gut was Ihr hier schreibt und vermutlich auch richtig.
Nach der Sinnhaftigkeit wird man aber schon fragen dürfen, ob man für eine signed 8 Bit Variable 3 bzw. 4 Verschiedene Definitionen braucht, die dann wiederum nur mit bestimmten Funktionen laufen. Eine Eindeutige sollte da doch auch reichen?
Ganz zu schweigen von den Sonderfunktionen, die man dann noch für die Flash und EEProm Behandlung braucht.

Mit diesen " Spielchen " hab Ich schon viel Zeit vertrödelt.

Aber da wird man wohl damit leben müssen.
Betrachten wir's positiv - Wieder was gelernt.

HaWe
19.01.2019, 19:54
Alles schön und gut was Ihr hier schreibt und vermutlich auch richtig.
Nach der Sinnhaftigkeit wird man aber schon fragen dürfen, ob man für eine signed 8 Bit Variable 3 bzw. 4 Verschiedene Definitionen braucht, die dann wiederum nur mit bestimmten Funktionen laufen. Eine Eindeutige sollte da doch auch reichen?
(...)
Mit diesen " Spielchen " hab Ich schon viel Zeit vertrödelt.

Aber da wird man wohl damit leben müssen.
Betrachten wir's positiv - Wieder was gelernt.

braucht man nicht -
char alleine reicht immer.
stdint ist eine extra Lib, die kam erst einiges später.
Aber C ist nun mal auf verschiedenen Libs aufgebaut, die alle ihre eigenen Regeln haben, und ein kurzer Blick in die Lib/Funktions-Definitionen zeigt ja auch sofort, was man braucht.
An der signed/unsigned char Problematik für AVR und ARM habe ich mir auch schon die Zähne ausgebissen und die Haare gerauft.
Aber wie es so schön heißt: RTFM ! :mrgreen: