Forum: PC-Programmierung strcmp() aus musl libc


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe die Funktion strcmp(...) aus musl libc

http://git.musl-libc.org/cgit/musl/tree/src/string/strcmp.c

mit der gleichen Funktion aus glibc

https://github.com/bminor/glibc/blob/master/string/strcmp.c

verglichgen.

Beide rechnen mit "unsigned char". Aber macht diese return-Anweisung aus 
musl-libc Sinn?
return *(unsigned char *)l - *(unsigned char *)r;
Wegen integer promotion wird doch die Subtraktion mit int's durchgeführt 
und dann das Ergebnis einem int-Rückgabewert zugewiesen. Also ist diese 
Typumwandlung an dieser Stelle gar nicht nötig.

Bei glibc wird ja gleich zu Beginn umgewandelt. Aber erst bei einer 
return-Aweisung? Das ist doch gar nicht nötig oder?

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> Wegen integer promotion wird doch die Subtraktion mit int's durchgeführt

Mal ganz generell gefragt: was genau hast du eigentlich mit der lib vor? 
Nutz die, wie sie ist, oder lass es.

Oliver

: Bearbeitet durch User
von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mal generell gefragt warum nein? Alles war "unter" int ist, wird bei 
Berechnungen als int / unsigned int  betrachtet oder nicht?

von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Überleg dir, was bei Zeichen außerhalb des Bereichs 0-127 passiert.

von Carl D. (jcw2)


Bewertung
0 lesenswert
nicht lesenswert
In der gnu-Version fallen mir unnötige casts auf, um const zu entfernen. 
Aber c1/c2 werden nie verändert. Die musl-Variante ist zwar sehr knapp 
gehalten, aber frei von solchen "Unzulänglichkeiten". Und der cast auf 
unsigned Char wird gebraucht, um Zeichen >127 korrekt zu vergleichen.

von zitter_ned_aso (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> return *(unsigned char *)l - *(unsigned char *)r;
> Wegen integer promotion wird doch die Subtraktion mit int's durchgeführt
> und dann das Ergebnis einem int-Rückgabewert zugewiesen. Also ist diese
> Typumwandlung an dieser Stelle gar nicht nötig.

nach langem Überlegen:

Integer promotion findet natürlich statt. Allerdings werden da falsche 
Zahlen zu Integer's befördert weil es bei den Buchstaben mit dem 
ASCII-Code > 127 einen Überlauf gibt (bei signed char). Und diese, 
falsche Zahl, wird nach "int" umgewandelt.

Bei mir funktioniert's übrigens auch wenn BEIDE Buchstaben >127 sind 
ohne explizite Typumwandlung.
return *l - *r;

Dann gibt es ja für beide einen Überlauf, aber der Abstand bleibt ja 
trotzdem gleich. Aber so ein Überlauf ist ja bei signed-Werten nicht 
definiert.Wenn es nur bei einem Buchstaben diesen Überlauf gibt, dann 
geht die Version ohne explizites Casten in die Hose.

Und dann habe ich noch eine Frage:
Warum wird die erste Variante akzeptiert und bei der zweiten - gewarnt?
 char str1[]="ü";                                                  
 char str2[]={'ü','\0'};  

von Carl D. (jcw2)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
>
> Bei mir funktioniert's übrigens auch wenn BEIDE Buchstaben >127 sind
> ohne explizite Typumwandlung.
>

Aber manchmal hat man <=127/>127 gemischt.
Z.B. "aaaa" vs. "ääää". Was sagt dann dein Algorithmus?

: Bearbeitet durch User
von zitter_ned_aso (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Carl D. schrieb:
> Z.B. "aaaa" vs. "ääää"

na dann bekomme ich ein falsches Ergebnis, habe ich doch oben 
geschrieben.


bei 'a' gibt es keine Überlauf, bei 'ä' schon.

zitter_ned_aso schrieb:
> Wenn es nur bei einem Buchstaben diesen Überlauf gibt, dann
> geht die Version ohne explizites Casten in die Hose.

von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Es gibt nirgendwo einen Überlauf.

Du hast ein 8-Bit-Muster und je nach Interpretation entspricht das 
-128..127 (signed char) oder 0..255 (unsgined char).  Die Erweiterung 
nach int ist in beiden Fällen eindeutig definiert und die folgende 
(int-)Subtraktion erfolgt ohne Überlauf, liefert aber je nach 
Interpretation unterschiedliche Ergebnisse.

ANSI-C verlangt bei strcmp (und auch bei memcmp) die 
unsigned-Interpretation.

von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Warum ist das kein Überlauf?

Ich kann das ja sogar nachbilden:
    int i=225;                                                          
    char ch=i; //Ueberlauf, da char==signed char                        
    int i_wrong = ch;                                                   
                                                                        
    printf("\ngegebener Integerwert: \t%d\n", i);                       
    printf("falscher Integerwert: \t%d\n", i_wrong);                    
    printf("Ueberlauf von  char: \t%d\n", ch);                          
    printf("auf uchar gecastet: \t%u\n", (unsigned char)ch);            
    printf("Ueberlauf berechnet: \t%d\n\n", (i%128)+(-128));  

und die Ausgabe (bei mir):
gegebener Integerwert:  225
falscher Integerwert:   -31
Ueberlauf von  char:    -31
auf uchar gecastet:     225
Ueberlauf berechnet:    -31

von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> Warum ist das kein Überlauf?

Äppel und Birnen?  Du wandelst von int nach char, strcmp von char nach 
int.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> Warum ist das kein Überlauf?

Es ist einfach nur eine andere Interpretierung der Bits.

Übrigens gibt es in C per Definition keine Überläufe.

: Bearbeitet durch User
von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Übrigens gibt es in C per Definition keine Überläufe.

Quelle bitte.

leo

von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> char str1[]="ü";
>  char str2[]={'ü','\0'};

so, als hex-Code geht's:
 char str2[]={'\xFC','\0'};                                             

aber in der Console wird dann
<fc> 

angezeigt. Im string werden die Zeichen aus dem erweiterten 
ASCII-Zeichensatz direkt akzeptiert, als einzelne char's jedoch nicht 
(egal ob signed/unsigned). Diese muss man dann codiert eingeben oder 
wchar nutzen.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
leo schrieb:
> Rolf M. schrieb:
>> Übrigens gibt es in C per Definition keine Überläufe.
>
> Quelle bitte.

Aus ISO/IEC 9899. Ok, stimmt nicht ganz. Bei Gleitkomma-Typen kann es 
Überläufe geben.

Zu unsigned Integern:

"A computation involving unsigned operands can never overflow,
because a result that cannot be represented by the resulting unsigned 
integer type is reduced modulo the number that is one greater than the 
largest value that can be represented by the resulting type."

Bei vorzeichenbehafteten Integern darf man nicht auf einen Überlauf 
vertrauen, da das Verhalten undefiniert ist. Dazu hab ich direkt keine 
Passage gefunden, außer vielleicht dieser:

"If an exceptional condition occurs during the evaluation of an 
expression (that is, if the result is not mathematically defined or not 
in the range of representable values for its type), the behavior is 
undefined.

: Bearbeitet durch User
von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Zu unsigned Integern:

Du hattest nur diese gemeint oder auch signed integer? Bei letzteren 
gibt es sicher Overflow.
$ pdftotext c-std-n1256.pdf - | grep -c overflow
33

leo

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
leo schrieb:
> Rolf M. schrieb:
>> Zu unsigned Integern:
>
> Du hattest nur diese gemeint oder auch signed integer?

Hatte ich doch geschrieben:

Rolf M. schrieb:
> Bei vorzeichenbehafteten Integern darf man nicht auf einen Überlauf
> vertrauen, da das Verhalten undefiniert ist.

leo schrieb:
> $ pdftotext c-std-n1256.pdf - | grep -c overflow
> 33

Das Wort "overflow" kommt schon vor, dennoch ist es so, dass unsigned 
integer nicht überlaufen können und ein Überlaufverhalten für 
signed-Integer nicht definiert ist.

von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> und ein Überlaufverhalten für
> signed-Integer nicht definiert ist.

Ja, haette ich genauer lesen muessen. Wie auch immer Overflow passiert 
;)

leo

von Jemand (Gast)


Bewertung
0 lesenswert
nicht lesenswert
7.17.7.5 The atomic_fetch and modify generic functions
[...]
For signed integer types, arithmetic is defined to use two’s
complement representation with silent wrap-around on overflow; there are no undefined
results. 

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.