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
WEAKchar*strchr(constchar*s,intc)
2
{
3
c=(unsignedchar)c;
4
if(!c)return(char*)s+strlen(s);
5
for(;*s&&*(unsignedchar*)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.
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):
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(constchar*s,charc)
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()":
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;
}
}