strchr und ch32v003 mit riscv-none-elf-gcc

#7858059
Lesenswert?

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:

1
         Das Zeichen wurde nicht gefunden

Der riscv-none-elf-gcc auf einem CH32V003 gibt mir aus:

1
         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 ?

#7858069
Lesenswert?

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.

#7858077
Lesenswert?

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.

#7858088
Lesenswert?

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. ;-)

#7858097
Lesenswert?

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
}
#7858104
Lesenswert?

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.

#7859020
Lesenswert?

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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren