Forum: Mikrocontroller und Digitale Elektronik strchr und ch32v003 mit riscv-none-elf-gcc


von Ralph S. (jjflash)


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:

             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 ?

von Harald K. (kirnbichler)


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.

von Harald K. (kirnbichler)


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.

von Wastl (hartundweichware)


Lesenswert?

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.

von Harald K. (kirnbichler)


Lesenswert?

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

von Norbert (der_norbert)


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

: Bearbeitet durch User
von Ralph S. (jjflash)


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
}

von Harald K. (kirnbichler)


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.

von Ralph S. (jjflash)


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
}

von F. P. (fail)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.