Beim Evaluieren mit einem CH32V003 kämpfe ich - wieder einmal - an einer
Ecke mit einem Problem, an der ich kein Problem erwartet habe.
Compiler ist: riscv-none-elf-gcc Version 14.2.0
Das Framework CH32FUN verwendet im Setup den Compilerschalter -nostdlib
Das kann man nicht entfernen, macht man es doch hageln viele
Fehlermeldungen
Grundsätzlich habe ich da mit den Bibliotheken ein Problem. Funktionen
aus <stdlib.h> wie bspw. rand sind nicht verfügbar. Okay, ist halt nicht
verfügbar.
Auch in <string.h> gibt es bspw. ein "toupper" nicht, okay, gibts halt
auch nicht (und ist ja auch schnell geschrieben).
Allerdings ein strchr gibt es und damit habe ich jetzt ein
Problem(chen):
Mit den Compilern
- avr-gcc
- arm-none-eabi-gcc
- gcc (in der PC-Konsole)
- sdcc 4.4 (auf einem STM8)
erfolgt mit folgendem Code: 1 | char string[120];
| 2 | char *ptr;
| 3 | char c;
| 4 |
| 5 | c= 'z';
| 6 |
| 7 | strcpy(string, "Dieses ist ein String");
| 8 |
| 9 | ptr = strchr(string, c);
| 10 |
| 11 | if (ptr)
| 12 | {
| 13 | printf("\n\rDas Zeichen %c wurde gefunden an Position: %d\n\r", c, ptr-string);
| 14 | }
| 15 | else
| 16 | {
| 17 | printf("\n\rDas Zeichen wurde nicht gefunden\n\r");
| 18 | }
|
Die aus meiner Sicht der Dinge die richtige Ausgabe:
Das Zeichen wurde nicht gefunden
Der riscv-none-elf-gcc auf einem CH32V003 gibt mir aus:
Das Zeichen z wurde gefunden an Position: 21
Woran liegt das?
Natürlich kann ich mir behelfen in der Art
if (ptr-string == (strlen(string)+1)
Aber das gefällt mir natürlich nicht. Ich kann auch ein eigenes strchr
programmieren (gefällt mir aber auch nicht).
Woran liegt das, dass der riscv-compiler (bzw. die Standardbibliothek
strchr) ein anderes Ergebnis bringt wie alle anderen Compiler ?
Ralph S. schrieb:
> Auch in <string.h> gibt es bspw. ein "toupper" nicht
Da gehörts auch nicht hin. Das ist in ctype.h deklariert.
Die Dateien namens *.h sind übrigens keine Libraries. Diesen
Ardunio-Sprech solltest Du Dir abgewöhnen.
Libraries heißen lib*.a und werden mit dem Linkerflag -l* verwendet.
D.h. um mit libfoo.a zu linken, musst Du -lfoo angeben.
Der Quelltext der Funktion strchr übrigens ist in ch32fun.c enthalten:
1 | WEAK char *strchr(const char *s, int c)
| 2 | {
| 3 | c = (unsigned char)c;
| 4 | if (!c) return (char *)s + strlen(s);
| 5 | for (; *s && *(unsigned char *)s != c; s++);
| 6 | return (char *)s;
| 7 | }
|
Die Funktion gibt keinen Nullpointer zurück, sondern einen Pointer auf
das gefundene Zeichen --oder auf das \0-Zeichen am Stringende.
Das ist eine ... merkwürdige Art, das zu machen.
Harald K. schrieb:
> Das ist eine ... merkwürdige Art, das zu machen.
Harald K. schrieb:
> Der Quelltext der Funktion strchr übrigens ist in ch32fun.c enthalten:
Wenn's ernst gemeint wäre würde es in ch32funct.c enthalten sein.
So ist es halt ein bisschen Spass.
Wastl schrieb:
> Wenn's ernst gemeint wäre würde es in ch32funct.c enthalten sein.
Bruha..ha.... ha.
Hier übrigens, falls es wer nicht glauben will:
https://github.com/cnlohr/ch32fun/blob/master/ch32fun/ch32fun.c#L384
Früher, in den Siebzigern, da hatten wir Wundertüten.
Immer gab's 'ne Überraschung!
Heute haben wir … ja was eigentlich? Volle Arduinoisierung erreicht?
PS. Damit ich nicht falsch verstanden werde, das ist doch lustig.
Wo steht geschrieben, dass sich der selbe Code stets gleich verhalten
soll. Das wäre ja die Definition von Langeweile. ;-)
Harald K. schrieb:
> Die Dateien namens *.h sind übrigens keine Libraries. Diesen
> Ardunio-Sprech solltest Du Dir abgewöhnen.
>
> Libraries heißen lib*.a und werden mit dem Linkerflag -l* verwendet.
>
> D.h. um mit libfoo.a zu linken, musst Du -lfoo angeben.
Okay, wenn es dir so lieber ist:
Eine Funktion die im Header <string.h> deklariert (nicht definiert) ist
und eine Funktion aus der Library aufruft, die statisch hinzugelinkt
wurde ..
Boah, ich weiß, dass man eine Bibliothek mit -lfoo hinzulinkt !
Außerdem: Ich programmiere nicht mit dem Arduino-Framework...
Harald K. schrieb:
> Hier übrigens, falls es wer nicht glauben will:
>
> https://github.com/cnlohr/ch32fun/blob/master/ch32fun/ch32fun.c#L384
Dort habe ich das auch gefunden. Weil ich das aber nicht dort ändern
möchte, hat mein Programm jetzt doch das hier (bekommen CH32-Programme
eben kein strchr):
1 | /* ----------------------------------------------------------
| 2 | strfindch
| 3 |
| 4 | sucht in einem String ein Zeichen.
| 5 |
| 6 | Liefert einen Zeiger auf das erste Vorkommen von
| 7 | ch in str bzw. den Wert NULL, wenn ch in str nicht
| 8 | enthalten ist.
| 9 |
| 10 | ==> Ersatz fuer strchr aus <string.h> welches mit dem
| 11 | CH32FUN Framework augenscheinlich nicht richtig
| 12 | funktioniert (liefert keinen NULL-Zeiger)
| 13 | ---------------------------------------------------------- */
| 14 | char *strfindch(char *str, char ch)
| 15 | {
| 16 |
| 17 | while(*str)
| 18 | {
| 19 | if (*str == ch) { return str; }
| 20 | str++;
| 21 | }
| 22 | return NULL;
| 23 | }
|
Ralph S. schrieb:
> Boah, ich weiß, dass man eine Bibliothek mit -lfoo hinzulinkt !
Du drückst Dich halt nicht so aus. Woher soll ich das ahnen?
Ralph S. schrieb:
> Weil ich das aber nicht dort ändern möchte,
Könntest Du aber problemlos. Das Attribut WEAK besagt, daß Du einfach
Deine eigene strchr-Implementierung gleichen Namens irgendwo anders
verwenden kannst, wenn Du die Library verwendest, in der ch32fun.c
enthalten ist.
Du könntest auch einen simplen Wrapper drumrumpacken:
1 | char *my_strchr(const char *s, char c)
| 2 | {
| 3 | char *p;
| 4 | p = strchr(s, c);
| 5 | return (*p ? p : NULL);
| 6 | }
|
Den sollte man natürlich nie auf ein richtiges strchr loslassen, sonst
knallts.
Nur der Vollständigkeit halber:
Mein Code von "strch()" ist auch nicht richtig, denn nach der
Beschreibung eines uralten Referncemanual aus 1987 zu Turbo C (das
stammt von meinem ersten gekauften C-Compiler -verrückt wie lange ich
schon mit C hantiere-) kann "strch()" auch das Zero-Zeichen am Ende
eines Strings finden und würde so auch die Länge eines Strings ermitteln
können ( :-) sollte strlen nicht funktionieren).
Deshalb der "erweiterte" Code zu "strch()":
1 | /* ----------------------------------------------------------
| 2 | strch
| 3 |
| 4 | Turbo C (Borland) original description:
| 5 |
| 6 | scans a string in the forward direction, looking for
| 7 | a specific character. strchr() finds the first
| 8 | occurrence of the character ch in the string "str".
| 9 |
| 10 | The null-terminator (\0) is considered to be part
| 11 | of the string, so that, for example
| 12 | strchr(strs, '\0') returns a pointer to the
| 13 | terminating null character of the string "str"
| 14 |
| 15 | Description:
| 16 |
| 17 | returns a pointer to the first occurrence of the
| 18 | character ch in str; if ch does not occur in str,
| 19 | strchr returns NULL.
| 20 | ---------------------------------------------------------- */
| 21 | char *strfindch(const char *str, char ch)
| 22 | {
| 23 | while(*str)
| 24 | {
| 25 | if (*str == ch) { return (char *)str; }
| 26 | str++;
| 27 | }
| 28 | if ((*str == 0) && (ch== '\0')) return (char *)str;
| 29 | return NULL;
| 30 | }
|
Das zweite Argument sollte ein int sein, kein char. Und der Code läßt
sich lesbarer formulieren:
char *strchr (const char *s, int c) {
for (;;) {
if (*s == (char)c)
return (char*)s;
if (*s == 0)
return NULL;
++s;
}
}
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|