Discussion:
CHAR_MIN, CHAR_MAX
(zu alt für eine Antwort)
Helmut Schellong
2016-10-10 15:23:40 UTC
Permalink
Das Verhalten des gcc war in Bezug auf 'char'
vor längerer Zeit anders als heute.

Ich vermute, wegen der Möglichkeit von Padding-Bits seit C99.

Früher hatte -funsigned-char den Compiler ruhiggestellt.
Wenn man durchgehend 'unsigned char' verwendete, bei Lib-Funktionen
mit 'char' und bei 'x= k>0 ? ucharptr : "Len"', gab es kein Gemecker.
So als ob jegliches 'char' wirklich als 'unsigned char' angesehen
würde, also auch "abc".

Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.

Ich verwende grundsätzlich -funsigned-char und sichere meine Programme
so ab:
#if CHAR_MIN != 0
# error "Option -funsigned-char (o.vglb.) fehlt!"
#endif

Heute muß ich
#define byte char
statt
#define byte unsigned char
geben.
Andernfalls erhalte ich nnnn Warnungen, trotz -funsigned-char.

-funsigned-char bewirkt aber doch:
CHAR_MIN = 0
CHAR_MAX = 255
und der Compiler verwendet grundsätzlich 'movzx' in Assembler, wenn
es um 'char' geht! Er behandelt 'char' konkret, als ob es wirklich
'unsigned char' wäre!
Meckert aber, wenn 'unsigned char' gemeinsam mit 'char' verwendet wird.

Es wird /heute/ also den unterschiedlichen Bezeichnern (dem literalen
Unterschied) 'char' und 'unsigned char' Vorrang eingeräumt gegenüber
der konkret vorliegenden Realität:
char: 0..255
unsigned char: 0..255
wird ignoriert.
Warnungen über unterschiedliche Signedness sind hier eine Falschaussage!
Weil _beide_ Typen tatsächlich kein Vorzeichen haben.

Die drei char-Typen sind unterschiedliche Typen, laut Standard. Ja.
Aber die Behauptungen der unterschiedlichen Signedness und inkompatiblen
Pointern ist oben dennoch falsch.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-11 06:10:27 UTC
Permalink
Post by Helmut Schellong
Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.
Hast du auch einen Testfall, der das demonstriert? So allgemein kann
man mit der Aussage erst mal nix anfangen.
Helmut Schellong
2016-10-11 12:02:24 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.
Hast du auch einen Testfall, der das demonstriert? So allgemein kann
man mit der Aussage erst mal nix anfangen.
http://www.schellong.de/txt/gccw
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-11 17:37:11 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.
Hast du auch einen Testfall, der das demonstriert? So allgemein kann
man mit der Aussage erst mal nix anfangen.
http://www.schellong.de/txt/gccw
Da stehen ein Haufen Fehlermeldungen, aber nicht genügend Informationen,
weil ein Beispiel-Quelltext fehlt.

Was willst du denn genau machen, worüber der gcc warnt?
Helmut Schellong
2016-10-11 22:11:12 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.
Hast du auch einen Testfall, der das demonstriert? So allgemein kann
man mit der Aussage erst mal nix anfangen.
http://www.schellong.de/txt/gccw
Da stehen ein Haufen Fehlermeldungen, aber nicht genügend Informationen,
weil ein Beispiel-Quelltext fehlt.
Was willst Du denn da heraus lesen?
Der gcc zeigt doch den Quelltext zu jedem Fehler.

Kontest Du denn nicht feststellen, daß der gcc unberechtigt die Warnungen
gibt? Darum geht es doch.
Post by Thomas Koenig
Was willst du denn genau machen, worüber der gcc warnt?
Ich will unsigned char verwenden, weil das der einzige Typ ist, der
keine Padding-Bits enthalten darf.
Genau das geht nicht, weil gcc diese '1000' Warnungen produziert.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-11 22:48:43 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.
Hast du auch einen Testfall, der das demonstriert? So allgemein kann
man mit der Aussage erst mal nix anfangen.
http://www.schellong.de/txt/gccw
Da stehen ein Haufen Fehlermeldungen, aber nicht genügend Informationen,
weil ein Beispiel-Quelltext fehlt.
Was willst Du denn da heraus lesen?
Der gcc zeigt doch den Quelltext zu jedem Fehler.
Mit einer Zeile Quelltext (ohne Kontext, wie z.B. die dazugehörigen
Deklarationen) kann man wenig anfangen.

Schreib ein vollständiges Programm, das den Fehler demonstriert, dann
kann man darüber diskutieren. So ist das vollkommen sinnlos.
Post by Helmut Schellong
Kontest Du denn nicht feststellen, daß der gcc unberechtigt die Warnungen
gibt?
Nein. Für jede der Warnungen (soweit ich sie mir angesehen habe - ich
habe selbstverständlich nicht vor, eine endlose Liste von Warnungen zu
einem Source-Code, den ich nicht kenne zu studieren und mir zu
überlegen, was da jetzt der Source-Code sein könnte) fällt mir ein
Kontext ein, in dem die berechtigt sein könnte. Wenn Du ein
Beispielprogramm postest, dann kann man darüber diskutieren, ob die
Warnungen berechtigt oder unberechtigt sind (Sowas ist natürlich immer
subjektiv).
Post by Helmut Schellong
Post by Thomas Koenig
Was willst du denn genau machen, worüber der gcc warnt?
Ich will unsigned char verwenden, weil das der einzige Typ ist, der
keine Padding-Bits enthalten darf.
Das ist in den Fällen, auf die sich die Warnungen zu beziehen scheinen,
eine originelle Begründung.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-11 23:09:46 UTC
Permalink
Post by Peter J. Holzer
Post by Helmut Schellong
Was willst Du denn da heraus lesen?
Der gcc zeigt doch den Quelltext zu jedem Fehler.
Mit einer Zeile Quelltext (ohne Kontext, wie z.B. die dazugehörigen
Deklarationen) kann man wenig anfangen.
Schreib ein vollständiges Programm, das den Fehler demonstriert, dann
kann man darüber diskutieren. So ist das vollkommen sinnlos.
Post by Helmut Schellong
Kontest Du denn nicht feststellen, daß der gcc unberechtigt die Warnungen
gibt?
Nein. Für jede der Warnungen (soweit ich sie mir angesehen habe - ich
habe selbstverständlich nicht vor, eine endlose Liste von Warnungen zu
einem Source-Code, den ich nicht kenne zu studieren und mir zu
überlegen, was da jetzt der Source-Code sein könnte) fällt mir ein
Kontext ein, in dem die berechtigt sein könnte. Wenn Du ein
Beispielprogramm postest, dann kann man darüber diskutieren, ob die
Warnungen berechtigt oder unberechtigt sind (Sowas ist natürlich immer
subjektiv).
# include <limits.h>

#if CHAR_MIN != 0 || CHAR_MAX != 255
# error "-funsigned-char fehlt!"
#endif

extern int f(char *);

int ff(void)
{
unsigned char buf[]= "ajdhowee;lsafjfhdqjyhjde";
return f(buf);
}

---------------------------------------------------------------

463] Gcc6 -S t.c
t.c: In function 'ff':
t.c:9:13: warning: pointer targets in passing argument 1 of 'f' differ in
signedness [-Wpointer-sign]
return f(buf);
^~~
t.c:5:12: note: expected 'char *' but argument is of type 'unsigned char *'
extern int f(char *);
^

Ich glaub' irgendwie nicht, daß ihr das jetzt versteht.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-12 06:26:15 UTC
Permalink
Post by Helmut Schellong
463] Gcc6 -S t.c
t.c:9:13: warning: pointer targets in passing argument 1 of 'f' differ in
signedness [-Wpointer-sign]
^^^^^^^^^^^^^^

Hier ist schon ein Hinweis, wie man das abstellen kann. Seit neuestem
schreibt gcc die Option, mit der eine Warnung erzeugt wurde, dazu.
Mit der entsprechenden -Wno- ... - Form kann man sie abstellen, wenn
sie stört. Sollte man typischerweise nach reiflicher Überlegung tun.

Ansonsten: Mit stock gcc passiert das so nicht. Das Kommando
heißt auch typischerweise nicht Gcc6. Ist das ein Skript, das
automatisch -Wall mit übergibt?

Wenn die Warnung richtig stört:

$ gcc -S -funsigned-char foo.c
$ gcc -S -funsigned-char -Wall foo.c
foo.c: In function 'ff':
foo.c:12:14: warning: pointer targets in passing argument 1 of 'f'
differ in signedness [-Wpointer-sign]
return f(buf);
^~~
foo.c:7:12: note: expected 'char *' but argument is of type 'unsigned
char *'
extern int f(char *);
^
$ gcc -S -funsigned-char -Wall -Wno-pointer-sign foo.c
$

Ob der Code jetzt sinnvoll ist oder nicht, will ich in diesem
Post nicht diskutieren. Abstellen lässt es sich auf jeden Fall.
Helmut Schellong
2016-10-12 12:22:54 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
463] Gcc6 -S t.c
t.c:9:13: warning: pointer targets in passing argument 1 of 'f' differ in
signedness [-Wpointer-sign]
^^^^^^^^^^^^^^
Hier ist schon ein Hinweis, wie man das abstellen kann. Seit neuestem
schreibt gcc die Option, mit der eine Warnung erzeugt wurde, dazu.
Mit der entsprechenden -Wno- ... - Form kann man sie abstellen, wenn
sie stört. Sollte man typischerweise nach reiflicher Überlegung tun.
Kenne ich alles schon lange:
:
set -f
MO="-DBSD -funsigned-char -static -s"
gcc6 \
-std=c11 -O1 $MO \
-Wl,-rpath=/usr/local/lib/gcc6 \
-masm=intel \
-fverbose-asm \
-Wall \
-Wno-unused-but-set-variable \
-Wno-maybe-uninitialized \
-Wno-char-subscripts \
-Wno-parentheses \
-Wno-empty-body \
-Wno-misleading-indentation \
-fno-builtin-strlen \
-falign-loops=4 -falign-jumps=8 -falign-functions=64 \
-funit-at-a-time \
-I/u/l/h $*

Ich will aber Warnungen zu pointer-sign unbedingt sehen, nur die
Falschmeldungen in Verbindung mit 'char' nicht.
Und es sind Falschmeldungen!
1000 unberechtigte Warnungen verstecken berechtigte Warnungen!

-funsigned-char
Let the type "char" be unsigned, like "unsigned char".

Each kind of machine has a default for what "char" should be. It
is either like "unsigned char" by default or like "signed char" by
default.

Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
But many programs have been written to use plain "char" and expect
it to be signed, or expect it to be unsigned, depending on the
machines they were written for. This option, and its inverse, let
you make such a program work with the opposite default.

The type "char" is always a distinct type from each of "signed
char" or "unsigned char", even though its behavior is always just
like one of those two.

Die man-Page sagt es ja, daß man idealerweise 'unsigned char' oder
'signed char', nicht aber 'char' verwenden soll.
Das tue ich seit Jahrzehnten.
Das Problem ist, daß Library-Funktionen als auch "abcdef" 'char'
verwenden, weshalb ich ja -funsigned-char verwende.
Damit konnte ich früher Warnungen abschalten, heute aber nicht mehr.

Ich will
#define byte unsigned char
geben, muß aber heute trotz -funsigned-char
#define byte char
geben, um die 1000 unberechtigten Warnungen nicht mehr zu sehen.

Ich werde z.B. nie (absichtlich) int* mit unsigned* vermischen.
Ebenso nicht Vorzeichen-char* mit unsigned char*, weshalb ich ja
grundsätzlich -funsigned-char gebe, welches ja Vorzeichen-char
zu unsigned-char wandelt, was vom Compiler jedoch ignoriert wird
bei der Warnungsausgabe.
1000 Falschwarnungen stören.
Post by Thomas Koenig
Ob der Code jetzt sinnvoll ist oder nicht, will ich in diesem
Post nicht diskutieren.
Demo-Code ist eigentlich nie sinnvoll.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Juergen Ilse
2016-10-12 13:38:56 UTC
Permalink
Hallo,
Post by Helmut Schellong
Ich will
#define byte unsigned char
geben, muß aber heute trotz -funsigned-char
#define byte char
geben, um die 1000 unberechtigten Warnungen nicht mehr zu sehen.
Die Warnungen sind nicht voellig unberechtigt, da auch mit -funsigned-char
char und unsigned char rein formal immer noch verschiedene Typen (wenn auch
mit identischem Wertebereich und identischer interner Darstellung sind).
Im Prinzip koennte der Compiler trotz dieser Option auch noch vor dem mischen
der Typen char und unsigned char warnen (mich wundert ehrlich gesagt etwas,
warum er das bei "-Wall" nicht tut).
Post by Helmut Schellong
1000 Falschwarnungen stören.
Dann bau in dein script noch einen Wrapper ein, der dir die 1000 deiner
Ansicht nach ueberfluessigen Warnungen ausfiltert, caste die Datentypen
in deinem Quelltext jeweils auf die passenden Typen oder verzichte auf
das mischen von char und unsigned char ohne cast (ebenso auf das mischen
der entsprechenden Pointer-Typen).

"-funsigned-char" besagt nicht, dass char und unsigned char die selben
Typen sind, sondern dass der Compiler fuer beide Typen den selben Werte-
bereich und die selbe interne Darstellung annehmen soll. Die Typen sind
dennoch nicht die selben Typen (der Wortlaut der Warnung ist nicht unbe-
dingt zutreffend, aber dass dort eine Warnung ausgegeben wird schon).
Wenn du zwei struct Datentypen definierst, die zwar intern die selbe
Darstellung haben, moechtest du vielleicht dennoch darueber informiert
werden, wenn du diese Datentypen mischst (weil sich in spaeteren Ver-
sionen des Quelltextes mal etwas aendern koennte, so dass beide Defi-
nitionen nicht mehr uebereinstimmen). Die von dir kritisierte Warnung
ist eine Warnung dieser Art: Mischen von unterschiedlichen Datentypen,
auch wenn sie die slbe interne Darstellung haben.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Helmut Schellong
2016-10-12 14:36:56 UTC
Permalink
On 10/12/2016 15:38, Juergen Ilse wrote:
[...]
Post by Juergen Ilse
Dann bau in dein script noch einen Wrapper ein, der dir die 1000 deiner
Ansicht nach ueberfluessigen Warnungen ausfiltert, caste die Datentypen
in deinem Quelltext jeweils auf die passenden Typen oder verzichte auf
das mischen von char und unsigned char ohne cast (ebenso auf das mischen
der entsprechenden Pointer-Typen).
Mein Start-Posting ist eher eine Information an alle, keine Frage.
Letztlich habe ich keine Probleme.
Ich gebe
#define byte char
und gut is.
Der Compiler spinnt nur bei der Warnung.
Er generiert korrekten char-Code mit unsigned-Verhalten (wegen
-funsigned-char).

Casts kann ich nicht leiden.
Ich kann die libc, soweit ich sie brauche, selbst entwickeln, aber
mit unsigned char; und auch Wrapper-Funktionen mit Cast.

Ich sehe das letztlich plattformspezifisch, und habe auch deshalb keine
wirklichen Probleme.
Auf ix86-Plattformen (auch OSX) kann es gar keine Probleme damit geben.
Unter x86_64 haben alle Pointer 64 Bits und 64 Wert-Bits, ein Byte
hat 8 Bits und es herrscht 2er-Komplement.
Padding-Bits gibt es nicht und wird es nie geben.
(Das wäre eine neue Plattform, die sich nicht durchsetzen würde.
Es sei denn, die Padding-Bits wären unsichtbar.)
(Ich glaube, auch Itanium hat keine Padding-Bits.)
Die Gestaltung der Hardware verhindert von Grund auf jegliches Problem.
Post by Juergen Ilse
Wenn du zwei struct Datentypen definierst, die zwar intern die selbe
Darstellung haben, moechtest du vielleicht dennoch darueber informiert
werden, wenn du diese Datentypen mischst
Ja, will ich.
Nur auf die falschen Warnungen (s.o.) kann ich verzichten.
Die verdecken Warnungen, die ich sehen will.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Heinz Saathoff
2016-10-13 06:47:22 UTC
Permalink
Post by Juergen Ilse
Post by Helmut Schellong
1000 Falschwarnungen stören.
Dann bau in dein script noch einen Wrapper ein, der dir die 1000 deiner
Ansicht nach ueberfluessigen Warnungen ausfiltert, caste die Datentypen
in deinem Quelltext jeweils auf die passenden Typen oder verzichte auf
das mischen von char und unsigned char ohne cast (ebenso auf das mischen
der entsprechenden Pointer-Typen).
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
So eine lokale Unterdrückung von Warnungen ist meiner Meinung nach
sinnvoller, als global mit Compileroption alle Quellen mit anderer
char Interpretation zu übersetzen.


- Heinz
Helmut Schellong
2016-10-13 09:54:22 UTC
Permalink
Post by Heinz Saathoff
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
Nö.
http://www.schellong.de/txt/gccw
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Heinz Saathoff
2016-10-13 10:32:52 UTC
Permalink
Post by Helmut Schellong
Post by Heinz Saathoff
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
Nö.
http://www.schellong.de/txt/gccw
Sieht aber so aus, denn
Zeile 451
Zeile 452
....

Also eine Stelle, initialisierung einer Tabelle


- Heinz
Helmut Schellong
2016-10-13 10:39:58 UTC
Permalink
Post by Heinz Saathoff
Post by Helmut Schellong
Post by Heinz Saathoff
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
Nö.
http://www.schellong.de/txt/gccw
Sieht aber so aus, denn
Zeile 451
Zeile 452
....
Also eine Stelle, initialisierung einer Tabelle
Aber nicht doch.

========================================
4184 Zeilen
bsh.c:8824:20: warning: pointer targets in passing argument 2 of 'writef'
differ in signedness [-Wpointer-sign]
writef(OXFD, "%s%s", *A, C>1?" ":NL);
^~~~~~
In file included from bsh.c:980:0:
mod/function.c:2483:13: note: expected 'unsigned char *' but argument is of
type 'char *'
========================================
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-13 17:35:43 UTC
Permalink
Post by Heinz Saathoff
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
Nö.
Doch (hatte ich auch schon geschrieben, aber vielleicht liest
Helmut ja ein bisschen selektiv).

#pragma GCC diagnostic ignored "-Wpointer-sign"

Siehe https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html .
Helmut Schellong
2016-10-13 20:42:15 UTC
Permalink
Post by Thomas Koenig
Post by Heinz Saathoff
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
Nö.
Doch (hatte ich auch schon geschrieben, aber vielleicht liest
Helmut ja ein bisschen selektiv).
Wie hartnäckig wird denn hier gegen die Warnungsliste geredet?!
Die 1000 Warnungen kommen von etwa 1000 verschiedenen Stellen!
Nicht von nur einer (1) Stelle!
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-14 23:13:33 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Post by Heinz Saathoff
Ich kenn den GCC jetzt nicht so, aber gibt's da evtl. ein pragma, mit
dem man Warnmeldungen für einen Bereich unterdrücken kann?
Diese 1000 Meldungen, von denen Helmut spricht, scheinen ja bei der
Initialisierung einer Tabelle aufzutreten. Also an einer einzelnen
Stelle.
Nö.
Doch (hatte ich auch schon geschrieben, aber vielleicht liest
Helmut ja ein bisschen selektiv).
Wie hartnäckig wird denn hier gegen die Warnungsliste geredet?!
Die 1000 Warnungen kommen von etwa 1000 verschiedenen Stellen!
Nicht von nur einer (1) Stelle!
In so einem Fall kann man die diversen Stellen z.B. in einer
Datei bzw. in einem bestimmten Bereich zusammenfassen.

Bei systemabhängigem Code ist das durchaus sinnvoll, dann weiss
man wenigstens, welche Teile man im Zweifelsfall anfassen muss.
Helmut Schellong
2016-10-14 23:36:29 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Wie hartnäckig wird denn hier gegen die Warnungsliste geredet?!
Die 1000 Warnungen kommen von etwa 1000 verschiedenen Stellen!
Nicht von nur einer (1) Stelle!
In so einem Fall kann man die diversen Stellen z.B. in einer
Datei bzw. in einem bestimmten Bereich zusammenfassen.
Die Stellen sind gleichmäßig im gesamten Projekt verstreut.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-15 11:11:01 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Wie hartnäckig wird denn hier gegen die Warnungsliste geredet?!
Die 1000 Warnungen kommen von etwa 1000 verschiedenen Stellen!
Nicht von nur einer (1) Stelle!
In so einem Fall kann man die diversen Stellen z.B. in einer
Datei bzw. in einem bestimmten Bereich zusammenfassen.
Die Stellen sind gleichmäßig im gesamten Projekt verstreut.
Na denne... wirst du wohl in den sauren Apfel beißen müssen, entweder
dein Projekt umzustellen oder auf die Warnung zu verzichten (oder
den Compiler patchen...)

Ich habe dein kleines Testprogramm mal durch verschiedene
Compiler gejagt. Ergebnis:

$ cat foo.c
# include <limits.h>

#if CHAR_MIN != 0 || CHAR_MAX != 255
# error "-funsigned-char fehlt!"
#endif

extern int f(char *);

int ff(void)
{
unsigned char buf[]= "ajdhowee;lsafjfhdqjyhjde";
return f(buf);
}
$ clang -c -Wall -funsigned-char foo.c
foo.c:12:14: warning: passing 'unsigned char [25]' to parameter of type
'char *' converts between pointers to integer
types with different sign [-Wpointer-sign]
return f(buf);
^~~
foo.c:7:20: note: passing argument to parameter here
extern int f(char *);
^
1 warning generated.
$ icc -c -Wall -funsigned-char foo.c
foo.c(12): warning #2601: argument of type "unsigned char *" is
incompatible with parameter of type "char *" in signedness
return f(buf);

Die beiden Compiler warnen nicht bezüglich des string literals,
aber sehr wohl bezüglich wegen des unsigned char * - Arguments
von f.
Helmut Schellong
2016-10-15 14:42:04 UTC
Permalink
On 10/15/2016 13:11, Thomas Koenig wrote:
[...]
Post by Thomas Koenig
$ icc -c -Wall -funsigned-char foo.c
foo.c(12): warning #2601: argument of type "unsigned char *" is
incompatible with parameter of type "char *" in signedness
return f(buf);
Die beiden Compiler warnen nicht bezüglich des string literals,
aber sehr wohl bezüglich wegen des unsigned char * - Arguments
von f.
Ja, und alle behaupten eine unterschiedliche Signedness, die jedoch
nicht vorhanden ist.
Der Compiler sollte erstens anders formulieren, und zweitens eine (1)
Meldung ganz zum Schluß abgeben, die die Realität und potentielle
(theoretisch) Gefahren mitteilt.

Ein wichtiger Punkt ist, daß bei jeglichen Kopieraktionen kein
Unterschied bestehen kann, sofern die Bitbreiten gleich sind.

Auch eine Funktion, die char* erwartet, aber unsigned char* erhält,
arbeitet intern in Unkenntnis davon.
Und das Verhalten muß gleich sein.
Der Standard verlangt das indirekt bei 2er-Komplement.
Signed Typen korrespondieren mit unsigned Typen, dergestalt, daß
sie gleich breit und alle Wertbits identisch sein müssen.
Bei 2er-Komplement ist es so, daß ein Vorzeichenbit das eine Mal
als solches und ein anderes Mal als Wertbit gelten kann.
Es gibt da keinen Unterschied.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-16 09:40:45 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Die beiden Compiler warnen nicht bezüglich des string literals,
aber sehr wohl bezüglich wegen des unsigned char * - Arguments
von f.
Ja, und alle behaupten eine unterschiedliche Signedness, die jedoch
nicht vorhanden ist.
Der Compiler sollte erstens anders formulieren, und zweitens eine (1)
Meldung ganz zum Schluß abgeben, die die Realität und potentielle
(theoretisch) Gefahren mitteilt.
Dann bin ich mal auf den hcc (Helmuts C-Compiler) gespannt, der
das implementiert. Du könntest gcc und/oder clang natürlich auch
forken

Wann finde ich das Projekt auf github? :-)
Thomas Koenig
2016-10-12 19:02:14 UTC
Permalink
Post by Helmut Schellong
Ich will aber Warnungen zu pointer-sign unbedingt sehen, nur die
Falschmeldungen in Verbindung mit 'char' nicht.
Und es sind Falschmeldungen!
Nope, aber das haben andere schon begründet.

Ich habe auch nicht verstanden, warum du unbedingt einen Pointer auf
unsigned char mit der Adresse eines string literals initialisieren
möchtest. Außer potentziellem Ärger mit späteren Versionen
des Compilers hast du damt gar nichts gewonnen, außer dass du
die C-Norm mal wieder nicht einhältst, aber das ist bei dir ja
sowieso Sport.

Wenn du aber die Meldungen unterdrücken willst, dann geht
das relativ einfach mit diagnostic pragmas, siehe
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html

Beispiel:

$ cat foo.c
# include <limits.h>

#if CHAR_MIN != 0 || CHAR_MAX != 255
# error "-funsigned-char fehlt!"
#endif

extern int f(char *);

int ff(void)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-sign"
#pragma message "Here be dragons"
unsigned char buf[]= "ajdhowee;lsafjfhdqjyhjde";
return f(buf);
#pragma GCC diagnostic pop
}
$ gcc -S -funsigned-char -Wall foo.c
foo.c: In function 'ff':
foo.c:13:9: note: #pragma message: Here be dragons
#pragma message "Here be dragons"
^~~~~~~

Solange du deine ganzen zweifelhaften Initialisierungen an einem
Ort versammelst hast, bekommst du GCC dazu zu schweigen.

Nur nochmal: Empfehlen würde ich den ganzen Krempel mit
unsigned char * nicht.
Post by Helmut Schellong
Damit konnte ich früher Warnungen abschalten, heute aber nicht mehr.
S.o.
Helmut Schellong
2016-10-12 20:37:52 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Ich will aber Warnungen zu pointer-sign unbedingt sehen, nur die
Falschmeldungen in Verbindung mit 'char' nicht.
Und es sind Falschmeldungen!
Nope, aber das haben andere schon begründet.
Der Wortlaut der Warnungen ist falsch.
Das haben andere (halbwegs) bestätigt.

Wenn der Compiler sagt, es läge unterschiedliche Vorzeichenbehaftung vor,
dies aber eindeutig nicht wahr ist, so handelt sich es um eine
Falschaussage, genau so wie 1+1=5 eine Falschaussage ist.
Post by Thomas Koenig
Ich habe auch nicht verstanden, warum du unbedingt einen Pointer auf
unsigned char mit der Adresse eines string literals initialisieren
möchtest. Außer potentziellem Ärger mit späteren Versionen
des Compilers hast du damt gar nichts gewonnen, außer dass du
die C-Norm mal wieder nicht einhältst, aber das ist bei dir ja
sowieso Sport.
Ich schrieb:
unsigned char buf[]= "owf4iuwewegwehjwe";
Das ist keine Pointer-Initialisierung.

Der Compiler kritisierte das deshalb auch nicht!
Dann müßte er auch uintv=charv; kritisieren.

Bei Rainer W. kritisierte er jedoch diese Stelle, weil dieser
unsigned char *buf= "owf4iuwewegwehjwe";
angab.

Warum habe ich so initialisiert?
Weil ich nachfolgend mit buf[] ohne Vorzeichenerweiterung
umgehen will.
Das ist alles ganz normal und konform.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-12 23:38:21 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Ich will aber Warnungen zu pointer-sign unbedingt sehen, nur die
Falschmeldungen in Verbindung mit 'char' nicht.
Und es sind Falschmeldungen!
Nope, aber das haben andere schon begründet.
Ich habe auch nicht verstanden, warum du unbedingt einen Pointer auf
unsigned char mit der Adresse eines string literals initialisieren
möchtest.
Weil

unsigned char msg[] = "Hello, world!";

sehr viel lesbarer ist als

unsigned char msg[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20,
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21 };

?
Post by Thomas Koenig
Außer potentziellem Ärger mit späteren Versionen
des Compilers hast du damt gar nichts gewonnen, außer dass du
die C-Norm mal wieder nicht einhältst,
Ist meiner Meinung nach standardkonform.

C11, §6.2.5, Absatz 15:
| The three types char, signed char, and unsigned char are collectively
| called the character types.

C11, §6.7.9, Absatz 14:
| An array of character type may be initialized by a character string
| literal or UTF−8 string literal, optionally enclosed in braces.
| Successive bytes of the string literal (including the terminating null
| character if there is room or if the array is of unknown size)
| initialize the elements of the array.

Das ist ja nicht das Problem. Das Problem ist, dass er danach diesen
(unsigned char *) ohne Cast einem (char *) zuweist. Und das ist halt
kein kompatibler Typ, daher die Warnung. Der Zugriff über den Pointer
ist aber wieder standardkonform:

C11, §6.5, Absatz 7:
| An object shall have its stored value accessed only by an lvalue
| expression that has one of the following types:88)
[...]
| — a type that is the signed or unsigned type corresponding to the
| effective type of the object,
[...]

int foo(char *);

unsigned char *p;

foo((char *)p);

ist also standardkonform.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Thomas Koenig
2016-10-13 06:17:08 UTC
Permalink
Post by Peter J. Holzer
Post by Thomas Koenig
Post by Helmut Schellong
Ich will aber Warnungen zu pointer-sign unbedingt sehen, nur die
Falschmeldungen in Verbindung mit 'char' nicht.
Und es sind Falschmeldungen!
Nope, aber das haben andere schon begründet.
Ich habe auch nicht verstanden, warum du unbedingt einen Pointer auf
unsigned char mit der Adresse eines string literals initialisieren
möchtest.
Weil
unsigned char msg[] = "Hello, world!";
sehr viel lesbarer ist als
unsigned char msg[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20,
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21 };
?
Aber warum unsigned char?

Au#erdem funktioniert natuerlich auch

unsigned char msg[] = { 'H', 'e', 'l', 'l', 'o' }; :-)

oder die #pragma diagnostics - Lösung, wenn man sich
unbedingt auf dieses dünne Eis begeben will.
Peter J. Holzer
2016-10-13 09:55:08 UTC
Permalink
Post by Thomas Koenig
Post by Peter J. Holzer
Post by Thomas Koenig
Post by Helmut Schellong
Ich will aber Warnungen zu pointer-sign unbedingt sehen, nur die
Falschmeldungen in Verbindung mit 'char' nicht.
Und es sind Falschmeldungen!
Nope, aber das haben andere schon begründet.
Ich habe auch nicht verstanden, warum du unbedingt einen
Pointer auf unsigned char mit der Adresse eines string literals
^^^^^^^^^^^^^^^^^^^^^^^^
Sorry, das habe ich falsch gelesen. Bei einem Pointer (keinem Array)
hat man natürlich das Signedness-Problem (lässt sich allerdings mit
einem Cast beheben).
Post by Thomas Koenig
Post by Peter J. Holzer
Post by Thomas Koenig
initialisieren möchtest.
Weil
unsigned char msg[] = "Hello, world!";
sehr viel lesbarer ist als
unsigned char msg[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20,
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21 };
?
Aber warum unsigned char?
unsigned char hat gegenüber char mehrere Vorteile: Man kennt den
Wertebereich, der entspricht dem, was man erwartet, die Arithmetik ist
einfacher, man kann Funktionen wie isdigit() direkt verwenden. Dem steht
im wesentlichen ein Nachteil gegenüber: Fast alle Library-Funktionen
erwarten (char *)-Argumente, man muss bei deren Aufruf also casten.

Wenn ich ein Programm in C schreiben würde, das ernsthaft Manipulationen
von Byte-Strings betreibt (z.B. einen Editor), würde ich wahrscheinlich
unsigned char verwenden (oder eher uint8_t).

Kein Grund für unsigned char ist die von Helmut angeführte Angst vor
Padding-Bits: Erstens sind Padding-Bits auch in signed char verboten,
zweitens müssten trotzdem alle "Zeichen" abbildbar sein und drittens ist
die Wahrscheinlichkeit, dass seine Shell jemals auf ein System mit
Padding-Bits portiert wird, von 0 nicht unterscheidbar.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-13 10:34:47 UTC
Permalink
[...]
Post by Peter J. Holzer
Post by Thomas Koenig
Aber warum unsigned char?
unsigned char hat gegenüber char mehrere Vorteile: Man kennt den
Wertebereich, der entspricht dem, was man erwartet, die Arithmetik ist
einfacher, man kann Funktionen wie isdigit() direkt verwenden. Dem steht
im wesentlichen ein Nachteil gegenüber: Fast alle Library-Funktionen
erwarten (char *)-Argumente, man muss bei deren Aufruf also casten.
So ist es, und ich hasse umfangreiches Casten.
Das ist es nicht nur: jegliches Zusammenkommen mit "abc" zieht Warnungen
nach sich.

Die Leute kennen nicht die Gefährlichkeit von vorzeichenbehaftetem char:
Ausdruck: c+=25, a*b+c;

c ist 'char' und hat seinen Wert von 110 auf 135 geändert, ist also
plötzlich negativ geworden!, nämlich -121 = 10000111.
Durch int-Promotion wird daraus: 11111111111111111111111110000111.

Ich will 'char' nicht mit Vorzeichen haben!!!
Post by Peter J. Holzer
Wenn ich ein Programm in C schreiben würde, das ernsthaft Manipulationen
von Byte-Strings betreibt (z.B. einen Editor), würde ich wahrscheinlich
unsigned char verwenden (oder eher uint8_t).
So ist es.
Post by Peter J. Holzer
und drittens ist
die Wahrscheinlichkeit, dass seine Shell jemals auf ein System mit
Padding-Bits portiert wird, von 0 nicht unterscheidbar.
Ja, das ist so. Ich verweigere mich solchen Prozessoren unbedingt.

Aber, bsh ist eines von Hunderten meiner Programme.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-13 17:40:34 UTC
Permalink
Post by Helmut Schellong
Ausdruck: c+=25, a*b+c;
c ist 'char' und hat seinen Wert von 110 auf 135 geändert, ist also
plötzlich negativ geworden!, nämlich -121 = 10000111.
Ja und?

"char" ist zunächst einmal ein Integer-Typ. Vorzeichen bei
Integern sind sowohl in C als auch in anderen Programmiersprachen
durchaus üblich :-)

Natürlich kann man argumentieren, dass das Vermischen von
Zeichen mit Integern, wie es in C erzwungen ist, eine schlechte
Design-Idee ist. Wer das nicht will, sollte kein C verwenden.
Helmut Schellong
2016-10-13 20:45:48 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Ausdruck: c+=25, a*b+c;
c ist 'char' und hat seinen Wert von 110 auf 135 geändert, ist also
plötzlich negativ geworden!, nämlich -121 = 10000111.
Ja und?
"char" ist zunächst einmal ein Integer-Typ. Vorzeichen bei
Integern sind sowohl in C als auch in anderen Programmiersprachen
durchaus üblich :-)
Das meine ich nicht, sondern es ist eine klassische Fehlerquelle, daß
char plötzlich negativen Inhalt bekommt, weil der Programmierer
nicht damit rechnet.
Deshalb gibt es die Warnung -Wchar-subscripts.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Jahns
2016-10-14 09:17:26 UTC
Permalink
Post by Helmut Schellong
Das meine ich nicht, sondern es ist eine klassische Fehlerquelle, daß
char plötzlich negativen Inhalt bekommt, weil der Programmierer
nicht damit rechnet.
Deshalb gibt es die Warnung -Wchar-subscripts.
Da signed overflow eh UB ist, macht das eigentlich auch nichts mehr.

Thomas
Thomas Jahns
2016-10-14 09:28:44 UTC
Permalink
Post by Thomas Jahns
Da signed overflow eh UB ist, macht das eigentlich auch nichts mehr.
Argh, mein Fehler: wegen Wandlung in int vor der Addition ist die nicht
wohldefinierte Operation die Zurückwandlung von int nach char.

Thomas
Rainer Weikusat
2016-10-14 13:57:20 UTC
Permalink
Post by Thomas Jahns
Post by Helmut Schellong
Das meine ich nicht, sondern es ist eine klassische Fehlerquelle, daß
char plötzlich negativen Inhalt bekommt, weil der Programmierer
nicht damit rechnet.
Deshalb gibt es die Warnung -Wchar-subscripts.
Da signed overflow eh UB ist, macht das eigentlich auch nichts mehr.
Leute, die der Ansicht sind, eine vollkommen normale und wohldefinierte
arithmetische Operation sei widerwaertig und fehlerhaft ('exceptional
condition') halten das Verhalten in solchen Faellen fuer durch die
C-Norm undefiniert.

Bedauerlicherweise definiert die C-Norm nicht, was 'exceptional
condition' eigentlich sein soll. Allerdings legt die Wortwahl an
verschiedenen Stellen,

The conversion of a floating constant shall not raise an
exceptional condition or a floating-point exception at execution
time.
[6.4.4.2|5]

C is compatible with LIA-1's trap requirements for arithmetic
operations, but not for math library functions (which are not
permitted to generate any externally visible exceptional
conditions).
[H.3.1.2|1]

nahe, das hier jemand an hardware overflow traps dachte und nicht an
gefuehlte Frontalhirnexplosionen aufgrund als unmathematisch empfundener
Eigenschaften real existierender Gegenstaende.
G.B.
2016-10-12 13:03:10 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
463] Gcc6 -S t.c
t.c:9:13: warning: pointer targets in passing argument 1 of 'f' differ in
signedness [-Wpointer-sign]
^^^^^^^^^^^^^^
Hier ist schon ein Hinweis, wie man das abstellen kann.
Nicht gut(*).

http://stackoverflow.com/questions/24767522/
passing-unsigned-char-array-to-string-functions

Es gibt da recht weit gehende Vermutungen:

"I think you may have found a bug introduced by one tiny clause in C11."
– Chrono Kitsune Jul 16 '14 at 1:11

Neben einer Antwort von Keith Thompson schreibt der selbe im Kommentar:

"That clause is about the _representation_ of characters. It doesn't
change the fact that calling strtok with an unsigned char* argument is
a constraint violation." – Keith Thompson May 29 '15 at 21:35


__
(*) Die Entwicklung zeitgenössischer Sprachen (Python, Ruby, ...)
und auch das "Büchereiwesen" leiden noch heute sehr an den Folgen
`char*` und `unsigned`. Dort ist der wunde Punkt schlechthin.
Helmut Schellong
2016-10-12 14:51:00 UTC
Permalink
Post by G.B.
(*) Die Entwicklung zeitgenössischer Sprachen (Python, Ruby, ...)
und auch das "Büchereiwesen" leiden noch heute sehr an den Folgen
`char*` und `unsigned`. Dort ist der wunde Punkt schlechthin.
Ja, das ist 'doof'.
Kurze Werte unterliegen ohnehin der int-Promotion.
Was soll denn da eine Vorzeichenbehaftung von char überhaupt?!
Es sollte nur den Typ 'char' geben, und der dann stets ohne Vorzeichen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Juergen Ilse
2016-10-12 15:13:09 UTC
Permalink
Hallo,
Post by Helmut Schellong
Post by G.B.
(*) Die Entwicklung zeitgenössischer Sprachen (Python, Ruby, ...)
und auch das "Büchereiwesen" leiden noch heute sehr an den Folgen
`char*` und `unsigned`. Dort ist der wunde Punkt schlechthin.
Ja, das ist 'doof'.
Kurze Werte unterliegen ohnehin der int-Promotion.
Was soll denn da eine Vorzeichenbehaftung von char überhaupt?!
Es sollte nur den Typ 'char' geben, und der dann stets ohne Vorzeichen.
Dazu wirst du dir dann aber deine eigene Sprache bauen muessen, denn der
C-standard sieht in dem Punkt anders aus (mit *3* unterschiedlichen Typen
von denen zwei in der Darstellung uebereinstimmen, wobei es implementation
defined ist, ob char mit unsigned char oder mit signed char uebereinstimmt).
Das wird auch mit absoluter Sicherheit nicht mehr am C-Standard geaendert.
Wenn du das geandert haben willst, such dir eine andere Sprache.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Helmut Schellong
2016-10-13 16:05:29 UTC
Permalink
Post by G.B.
http://stackoverflow.com/questions/24767522/
passing-unsigned-char-array-to-string-functions
"That clause is about the _representation_ of characters. It doesn't
change the fact that calling strtok with an unsigned char* argument is
a constraint violation." – Keith Thompson May 29 '15 at 21:35
7.24 String handling <string.h>
For all functions in this subclause, each character shall be interpreted
as if it had the type unsigned char (and therefore every possible object
representation is valid and has a different value).

Für mich heißt das, daß man so tun soll, als ob jedes Zeichen
den Typ unsigned char hätte.

Was bedeutet das in strcmp?
return *s1 - *s2;
unsigned: 128-'a' = 31 ; 200-'a' = 103 ; 129-+128 = 1
signed: -128-'a' = -225 ; -56-'a' =-153 ;-127--128 = 1
So möchte ich nicht sortieren.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-13 19:47:07 UTC
Permalink
Post by Helmut Schellong
Post by G.B.
http://stackoverflow.com/questions/24767522/
passing-unsigned-char-array-to-string-functions
"That clause is about the _representation_ of characters. It doesn't
change the fact that calling strtok with an unsigned char* argument is
a constraint violation." – Keith Thompson May 29 '15 at 21:35
7.24 String handling <string.h>
For all functions in this subclause, each character shall be interpreted
as if it had the type unsigned char (and therefore every possible object
representation is valid and has a different value).
Für mich heißt das, daß man so tun soll, als ob jedes Zeichen
den Typ unsigned char hätte.
Wenn "man" eine "function in this subclause" ist, dann ja.
Post by Helmut Schellong
Was bedeutet das in strcmp?
return *s1 - *s2;
Dass diese Zeile falsch (oder zumindest nicht portabel) ist, wenn s1 und
s2 den Typ (char *) haben.

Zwei naheliegende standardkonforme Implementationen von strcmp wären
also:

int strcmp(const char *s1, const char *s2) {
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
while (*p1 == *p2 && *p1) {
p1++;
p2++;
};
return *p1 - *p2;
}

int strcmp(const char *s1, const char *s2) {
while (*s1 == *s2 && *s1) {
s1++;
s2++;
};
return (unsigned char)*s1 - (unsigned char)*s2;
}

Ganz ohne Cast kommt man also nicht aus.

Anmerkungen:

Der Zugriff auf ein Objekt mit effektivem Typ (char) über einen
(unsigned char *) ist erlaubt.

In einer /hosted implementation/ muss INT_MAX >= UCHAR_MAX sein, die
Subtraktion kann daher keinen Overflow produzieren. In einer
/freestanding implementation/ wäre ein Overflow möglich, aber dort muss
es kein strcmp geben. Sinnvollerweise würde man allerdings dort den
Vergleich am Schluss entsprechend anders formulieren.

Die erste Variante (Parameter haben einen Typ, werden aber sofort
Variablen eines anderen, besser geeigneten Typs zugewiesen) ist ein
relativ häufiges Pattern bei mir. Der Compiler kann das trivial
wegoptimieren und der Rest der Funktion bleibt von Casts verschont.

Beide Funktionen habe ich ungetestet so hingeschrieben. Wer Tippfehler
findet, darf sie behalten. Wer interessante Fehler findet, möge sie aber
bitte präsentieren.
Post by Helmut Schellong
unsigned: 128-'a' = 31 ; 200-'a' = 103 ; 129-+128 = 1
signed: -128-'a' = -225 ; -56-'a' =-153 ;-127--128 = 1
So möchte ich nicht sortieren.
Musst Du auch nicht, weil der Standard eh was anderes vorschreibt.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-13 21:03:03 UTC
Permalink
Post by Peter J. Holzer
Post by Helmut Schellong
7.24 String handling <string.h>
For all functions in this subclause, each character shall be interpreted
as if it had the type unsigned char (and therefore every possible object
representation is valid and has a different value).
Für mich heißt das, daß man so tun soll, als ob jedes Zeichen
den Typ unsigned char hätte.
Wenn "man" eine "function in this subclause" ist, dann ja.
Post by Helmut Schellong
Was bedeutet das in strcmp?
return *s1 - *s2;
Dass diese Zeile falsch (oder zumindest nicht portabel) ist, wenn s1 und
s2 den Typ (char *) haben.
Man soll so formulieren, steht doch oben.
"each character shall be interpreted as if it had the type unsigned char"
"Jedes Zeichen soll so interpretiert werden als ob es den Typ unsigned char
hätte."
Post by Peter J. Holzer
Zwei naheliegende standardkonforme Implementationen von strcmp wären
[...]
Post by Peter J. Holzer
Ganz ohne Cast kommt man also nicht aus.
Soll man aber ausdrücklich!
Man soll so tun, als handelte es sich bereits um unsigned char.

Kann ich kein Englisch, oder was liegt hier vor?
(Ich caste auch immer.)
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-13 21:32:05 UTC
Permalink
Post by Helmut Schellong
Post by Peter J. Holzer
Post by Helmut Schellong
7.24 String handling <string.h>
For all functions in this subclause, each character shall be interpreted
as if it had the type unsigned char (and therefore every possible object
representation is valid and has a different value).
Für mich heißt das, daß man so tun soll, als ob jedes Zeichen
den Typ unsigned char hätte.
Wenn "man" eine "function in this subclause" ist, dann ja.
Post by Helmut Schellong
Was bedeutet das in strcmp?
return *s1 - *s2;
Dass diese Zeile falsch (oder zumindest nicht portabel) ist, wenn s1 und
s2 den Typ (char *) haben.
Man soll so formulieren, steht doch oben.
"each character shall be interpreted as if it had the type unsigned char"
"Jedes Zeichen soll so interpretiert werden als ob es den Typ unsigned char
hätte."
Das ist keine Anweisung für den Programmierer, sondern eine Vorschrift,
wie sich die Implementation zu verhalten hat. Menschenskind, hast Du
noch nie einen Standard gelesen?

Konkret heißt das z.B., dass
strcmp("\x80", "\x7F")
einen positiven Wert zurückliefern muss, unabhängig davon, ob ein char
signed oder unsigned ist.

Es heißt auch z.B. dass memcmp die Bytes 0x00 und 0x80 auch auf einer
Sign-Magnitude-Architektur (wo sie (als signed char interpretiert) die
Werte +0 und -0 hätten) nicht als gleich ansehen darf.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Juergen Ilse
2016-10-13 22:36:09 UTC
Permalink
Hallo?
Post by Peter J. Holzer
In einer /hosted implementation/ muss INT_MAX >= UCHAR_MAX sein, die
Subtraktion kann daher keinen Overflow produzieren.
Bist du dir da wirklich *ganz* sicher? Ich bin mir da nicht so sicher.
Es gab mal eine C-Implementierung fuer einen Micro-Controller (war es
fuer die TNS32000 Serie?), wo sizeof(long) 1 war. Wenn du recht haettest,
waere damit eine standardkonforme hosted implementation nicht moegich ...
Ich weiss, dass UINT_MAX >= UCHAR_MAX sein muss, aber ob das auch
fuer INT_MAX gelten muss, da bin ich mir wirklich nicht sicher (ich
neige dazu, das zu bezweifeln).

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Peter J. Holzer
2016-10-14 13:17:51 UTC
Permalink
Post by Juergen Ilse
Post by Peter J. Holzer
In einer /hosted implementation/ muss INT_MAX >= UCHAR_MAX sein, die
Subtraktion kann daher keinen Overflow produzieren.
Bist du dir da wirklich *ganz* sicher?
Nicht ganz. Es steht nämlich nirgends explizit und ein paar Schritte in
der Argumentationskette kann man, wenn man advocatus diaboli spielen
will, anzweifeln. Aber ich halte die Argumentation für korrekt und würde
behaupten, dass niemand ernsthaft eine solche Implementation entwickeln
und als standardkonform verkaufen würde. Ein Language Lawer würde
vielleicht konzedieren, dass man vielleicht den Standard so auslegen
könnte, aber die User würden den Metzger Dick aus Henry VI zitieren.

(1) A binary stream is an ordered sequence of characters that can
transparently record internal data. (§7.21.2)

(2) Data read in from a binary stream shall compare equal to the data
that were earlier written out to that stream, under the same
implementation. (§7.21.2)

Man kann also jeden beliebigen unsigned char auf einen Stream schreiben
und zurücklesen.

(3) int fgetc(FILE *stream); (§7.21.7.1)

(4) If the end-of-file indicator for the input stream pointed to by
stream is not set and a next character is present, the fgetc
function obtains that character as an unsigned char converted to an
int and advances the associated file position indicator for the
stream (if defined).

(5) If the end-of-file indicator for the stream is set, or if the stream
is at end-of-file, the end-of-file indicator for the stream is set
and the fgetc function returns EOF. Otherwise, the fgetc function
returns the next character from the input stream pointed to by
stream. If a read error occurs, the error indicator for the stream
is set and the fgetc function 289) returns EOF. (§7.21.7.1)

(6) An end-of-file and a read error can be distinguished by use of the
feof and ferror functions. (§7.21.7.1, footnote 289)

Die Funktion fgetc kann also entweder jeden beliebigen Wert, den
unsigned char annehmen kann, zurückliefern, oder EOF. Dass EOF keiner
dieser Werte sein kann, muss man etwas indirekt erschließen: EOF ist
negativ, die gelieferten Zeichen sollen aber "as an unsigned char
converted to an int" geliefert werden. Die Umwandlung von Werten >
INT_MAX in int ist aber nicht wohldefiniert. Die Intention ist wohl,
dass alle möglichen Zeichen nicht-negativ sind. Weiters weist die
Fußnote darauf hin, dass man zur Unterscheidung von end-of-file und
Lesefehlern die Funktionen feof und ferror braucht. Sie weist nicht
darauf hin, dass das auch zur Unterscheidung von EOF und einem gültigen
Zeichen notwendig sein könnte. Auch wenn die Fußnote nicht normativ ist,
ist das wohl ein Indiz darauf, dass EOF sich von jedem gültigen Zeichen
unterscheiden muss.

Es gibt ein paar weitere Stellen, die ebenfalls darauf hinweisen, dass
EOF nicht gleich einem unsigned char-Wert sein kann (z.B. in
§7.21.7.10).

Daraus folgt also, dass int einen Wertebereich haben muss, der um
mindestens 1 größer ist als der von unsigned char. Keine der erlaubten
Repräsentationen von signed int kann in der gleichen Anzahl von Bits
mehr Werte unterbringen als ein unsigned char. Man braucht also
mindestens ein Bit mehr, wodurch alle unsigned char-Werte im
nicht-negativen Bereich Platz finden. Somit ist INT_MAX >= UCHAR_MAX.
Post by Juergen Ilse
Ich bin mir da nicht so sicher. Es gab mal eine C-Implementierung fuer
einen Micro-Controller (war es fuer die TNS32000 Serie?), wo
sizeof(long) 1 war.
In meinem Fall war's ein Motorola 96k. Aber das sind halt
Micro-Controller bzw. DSPs, die C-Implementationen sind da
typischerweise freestanding.
Post by Juergen Ilse
Wenn du recht haettest, waere damit eine standardkonforme hosted
implementation nicht moegich ...
Man könnte die vorhandene freestanding Implementation nicht kompatibel
zu einer hosted Implementation erweitern. Ja, dieser Meinung bin ich.

Es wäre meiner Meinung nach auch nicht sonderlich sinnvoll: Eine stdio,
die nicht auf 8-Bit-Bytes aufbaut, hätte ziemliche Probleme, mit der
Außenwelt zu kommunizieren.

Wenn man auf einer wortorientierten 32-Bit-Architektur eine hosted
Implementation bräuchte, wäre es wahrscheinlich besser, in den sauren
Apfel zu beißen und ein char = 8 Bit zu definieren. Das macht Zugriffe
auf char langsam, und die Repräsentation von char* und void*
inkompatibel mit anderen Pointern, aber die Alternative wäre eine zum
Rest der Welt inkompatible libc und das reduziert den Wert einer hosted
Implementation doch erheblich.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Juergen Ilse
2016-10-14 14:07:26 UTC
Permalink
Hallo,
Post by Peter J. Holzer
Post by Juergen Ilse
Post by Peter J. Holzer
In einer /hosted implementation/ muss INT_MAX >= UCHAR_MAX sein, die
Subtraktion kann daher keinen Overflow produzieren.
Bist du dir da wirklich *ganz* sicher?
Nicht ganz. Es steht nämlich nirgends explizit und ein paar Schritte in
der Argumentationskette kann man, wenn man advocatus diaboli spielen
will, anzweifeln. Aber ich halte die Argumentation für korrekt und würde
behaupten, dass niemand ernsthaft eine solche Implementation entwickeln
und als standardkonform verkaufen würde. Ein Language Lawer würde
vielleicht konzedieren, dass man vielleicht den Standard so auslegen
könnte, aber die User würden den Metzger Dick aus Henry VI zitieren.
Du solltest aber auch beachten, dass strcmp *nicht* *zwingend* die Differenz
der ersten nicht uebereinstimmenden chars zurueckgeben muss, sondern ledig-
lich einen (beliebigen) Wert <0 =0 oder >0 (abhaengig davon, ob das erste
nicht uebereinstimmende Zeichen nun kleiner gleich oder groesser des ent-
sprechenden Zeichens der zweiten Zeichenkette ist).
Post by Peter J. Holzer
(1) A binary stream is an ordered sequence of characters that can
transparently record internal data. (§7.21.2)
(2) Data read in from a binary stream shall compare equal to the data
that were earlier written out to that stream, under the same
implementation. (§7.21.2)
Man kann also jeden beliebigen unsigned char auf einen Stream schreiben
und zurücklesen.
(3) int fgetc(FILE *stream); (§7.21.7.1)
(4) If the end-of-file indicator for the input stream pointed to by
stream is not set and a next character is present, the fgetc
function obtains that character as an unsigned char converted to an
int and advances the associated file position indicator for the
stream (if defined).
Falls der Wert des unsigned char ausserhalb des positiven Wertebereichs
von int liegt, ist diese Konvertierung doch aber IIRC "implementation
defined" und nicht "undefined", solglich ist das bis jetzt noch kein
Argument gegen eine Implementierung, bei der der positive Wertebereich
von int kleiner als der positive Wertebereich von unsigned char waere ...
Post by Peter J. Holzer
(5) If the end-of-file indicator for the stream is set, or if the stream
is at end-of-file, the end-of-file indicator for the stream is set
and the fgetc function returns EOF. Otherwise, the fgetc function
returns the next character from the input stream pointed to by
stream. If a read error occurs, the error indicator for the stream
is set and the fgetc function 289) returns EOF. (§7.21.7.1)
Wo steht, dass EOF von allen Werten unterschiedlich sein muss, die sich
aus der Konvertierung nach int von beliebiegen unsigned char Werten er-
zeugen lassen? Der Standard setzt das IMHO nicht wirklich *zwingend* voraus.
Post by Peter J. Holzer
Die Funktion fgetc kann also entweder jeden beliebigen Wert, den
unsigned char annehmen kann, zurückliefern, oder EOF. Dass EOF keiner
dieser Werte sein kann, muss man etwas indirekt erschließen: EOF ist
negativ, die gelieferten Zeichen sollen aber "as an unsigned char
converted to an int" geliefert werden.
Korrekt. Und wenn der positive Wertebereich von int kleiner als der
Wertebereich von unisgned char ist, koennten bei dieser Konvertierung
auch negative Werte herauskommen (das Ergebnis der Konvertierung waere
in diesem Fall IMHO implementation defined).
Post by Peter J. Holzer
Die Umwandlung von Werten > INT_MAX in int ist aber nicht wohldefiniert.
Ich bin jetzt zu faul nachzulesen, aber ich bin ziemlich sicher, dass das
Ergebnis in diesem Fall "implementation defined" waere. Waer es "undefined"
koennte man daraus tatsaechlich folgen, dass keine hosted Implementierung
sieof(int)==1 zulassen duerfte, aber wie gesaagt bin ich da ziemlich sicher,
dass das nur "implementation defined" und nicht etwa "undefined" waere ...
Post by Peter J. Holzer
Die Intention ist wohl, dass alle möglichen Zeichen nicht-negativ sind.
Weiters weist die Fußnote darauf hin, dass man zur Unterscheidung von
end-of-file und Lesefehlern die Funktionen feof und ferror braucht.
Korrekt.
Post by Peter J. Holzer
Sie weist nicht darauf hin, dass das auch zur Unterscheidung von EOF und
einem gültigen Zeichen notwendig sein könnte.
Es wird aber auch nicht explizit gesagt, dass EOF von allen moeglichen
return-Werten beim lesen von unsigned char unterschiedlich sein muss.
Post by Peter J. Holzer
Auch wenn die Fußnote nicht normativ ist, ist das wohl ein Indiz darauf,
dass EOF sich von jedem gültigen Zeichen unterscheiden muss.
Es steht aber IMHO nicht *explizit* im Standard.
Post by Peter J. Holzer
Es gibt ein paar weitere Stellen, die ebenfalls darauf hinweisen, dass
EOF nicht gleich einem unsigned char-Wert sein kann (z.B. in
§7.21.7.10).
EOF kann auch nicht mit einem unsigned char uebereinstimmen (weil IIRC
EOF<0 sein muss), aber es ist IMHO durch den Standard nicht vorgeschrieben,
dass EOF zwingend von jedem moeglichen unsigned char Wert *nach* *int*
*konvertiert* verschieden sein muss ...
Post by Peter J. Holzer
Daraus folgt also, dass int einen Wertebereich haben muss, der um
mindestens 1 größer ist als der von unsigned char.
Du interpretierst sehr viel in den Standard hinein, was nicht explizit
drin steht (was aber i.d.R. gegeben ist, wenn der positive Wertebereich
von int groesser ist als der Wertebereich von unsigned char).
Post by Peter J. Holzer
Man könnte die vorhandene freestanding Implementation nicht kompatibel
zu einer hosted Implementation erweitern. Ja, dieser Meinung bin ich.
Und da bin ich anderer Meinung (zumindest was die hier von dir vorgebrachten
Argumente angeht).
Post by Peter J. Holzer
Es wäre meiner Meinung nach auch nicht sonderlich sinnvoll: Eine stdio,
die nicht auf 8-Bit-Bytes aufbaut, hätte ziemliche Probleme, mit der
Außenwelt zu kommunizieren.
Das sind alles Probleme, die sich loesen liessen.
Post by Peter J. Holzer
Wenn man auf einer wortorientierten 32-Bit-Architektur eine hosted
Implementation bräuchte, wäre es wahrscheinlich besser, in den sauren
Apfel zu beißen und ein char = 8 Bit zu definieren.
Da koenntest du Recht haben. Darum ging es hier aber nicht, sondern eher
um die theoretische Machbarkeit einer Implementierung mit sizeof(int)==1.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Peter J. Holzer
2016-10-14 17:26:50 UTC
Permalink
Post by Juergen Ilse
Hallo,
Post by Peter J. Holzer
Post by Juergen Ilse
Post by Peter J. Holzer
In einer /hosted implementation/ muss INT_MAX >= UCHAR_MAX sein, die
Subtraktion kann daher keinen Overflow produzieren.
Bist du dir da wirklich *ganz* sicher?
Nicht ganz. Es steht nämlich nirgends explizit und ein paar Schritte in
der Argumentationskette kann man, wenn man advocatus diaboli spielen
will, anzweifeln. Aber ich halte die Argumentation für korrekt und würde
behaupten, dass niemand ernsthaft eine solche Implementation entwickeln
und als standardkonform verkaufen würde. Ein Language Lawer würde
vielleicht konzedieren, dass man vielleicht den Standard so auslegen
könnte, aber die User würden den Metzger Dick aus Henry VI zitieren.
Du solltest aber auch beachten, dass strcmp *nicht* *zwingend* die Differenz
der ersten nicht uebereinstimmenden chars zurueckgeben muss,
Äh, ja? Wie kommst Du auf die seltsame Idee, dass ich dieser Meinung
wäre?

Wenn ich eine Implementation gepostet hätte, die -1, 0, +1
zurückliefert, hättest Du mir dann schroff aufgetragen, zu beachten,
dass strcmp nicht zwingend diese drei Werte zurückliefern muss?

[...]
Post by Juergen Ilse
Es steht aber IMHO nicht *explizit* im Standard.
Du wiederholst mich. Das war mein zweiter Satz in dem Posting, auf das
Du geantwortet hast. Es ergibt sich implizit daraus, dass etliche
Funktionen nicht funktionieren, wenn EOF == (int)uc für irgendeinen
unsigned char Wert uc ist. Nehmen wir z.B. ungetc:

| One character of pushback is guaranteed.
[...]
| If the value of c equals that of the macro EOF, the operation fails

Für mich ist das ein klarer Widerspruch. Wenn es einen unsigned char
Wert uc gibt, für den (int)uc = EOF ist, dann muss ungetc für diesen
gleichzeitig funktionieren (weil "one character of pushback guaranteed
ist") und nicht funktionieren ("the operation fails").

Du wirst jetzt möglicherweise argumentieren, dass da nicht explizit
steht, dass der Pushback für jedes mögliche Zeichen garantiert ist,
sondern nur für "ein Zeichen". Vielleicht nur für 'A'.

Ich werde jetzt nicht alle Beispiele, die mir einfallen, aufführen,
geschweige denn systematisch nach solchen suchen. Ich habe da kein
Missionierungsbedürfnis. Wenn Du der Meinung bist, dass eine solche
Implementation standardkonform sei, bitte. Die Wahrscheinlichkeit, dass
Du sie implementierst, und ich sie benützen muss, geht gegen 0.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-14 18:31:02 UTC
Permalink
On 10/14/2016 16:07, Juergen Ilse wrote:
[...]
Post by Juergen Ilse
Wo steht, dass EOF von allen Werten unterschiedlich sein muss, die sich
aus der Konvertierung nach int von beliebiegen unsigned char Werten er-
zeugen lassen? Der Standard setzt das IMHO nicht wirklich *zwingend* voraus.
Das spielt keine Rolle.
EOF muß sich zwingend von allen anderen Zeichen unterscheiden, weil
andernfalls eine Nutzung solcher get-Funktionen nicht möglich ist.
Jegliches Geschreibsel drumherum wäre dann sinnlos;
und die Sache kann stark abgekürzt werden.

Ich selbst verwende hier nur die POSIX-Funktion
ssize_t read(int, void*, size_t);
nbuf= read(fd, buf, nmax);
weil ich das einzig für professionell halte.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-12 12:53:01 UTC
Permalink
Post by Helmut Schellong
Post by Peter J. Holzer
Post by Helmut Schellong
Kontest Du denn nicht feststellen, daß der gcc unberechtigt die Warnungen
gibt?
Nein. Für jede der Warnungen
[...]
Post by Helmut Schellong
Post by Peter J. Holzer
fällt mir ein Kontext ein, in dem die berechtigt sein könnte. Wenn Du
ein Beispielprogramm postest, dann kann man darüber diskutieren, ob
die Warnungen berechtigt oder unberechtigt sind (Sowas ist natürlich
immer subjektiv).
# include <limits.h>
#if CHAR_MIN != 0 || CHAR_MAX != 255
# error "-funsigned-char fehlt!"
#endif
extern int f(char *);
int ff(void)
{
unsigned char buf[]= "ajdhowee;lsafjfhdqjyhjde";
return f(buf);
}
---------------------------------------------------------------
463] Gcc6 -S t.c
t.c:9:13: warning: pointer targets in passing argument 1 of 'f' differ in
signedness [-Wpointer-sign]
return f(buf);
^~~
t.c:5:12: note: expected 'char *' but argument is of type 'unsigned char *'
extern int f(char *);
^
Die Warnung ist absolut berechtigt. (char *) und (unsigned char *) sind
keine kompatiblen Typen. char muss zwar die gleiche Repräsentation haben
wie entweder signed char oder unsigned char, ist aber ein dritter Typ,
der mit keinem der beiden kompatibel ist.

Man bekommt auch genau die gleiche Meldung bei

extern int f(char *);

int ff(void)
{
signed char buf[]= "ajdhowee;lsafjfhdqjyhjde";
return f(buf);
}

wenn man mit -Wall -fsigned-char kompiliert.

Darüber, ob "differ in signedness" die bestmögliche Formulierung ist,
kann man streiten, aber ich halte es nicht für falsch: Die "signedness"
von "signed char" ist "signed", die von "unsigned char" ist "unsigned"
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.

Warnungen sollen auch vor unportablen Konstruktionen warnen. Auch wenn
bei deiner Implementation char unsigned ist, ist sie es bei anderen
vielleicht nicht. So wie vielleicht bei deiner Implementation int und
long die gleiche Repräsentation haben, auf anderen aber nicht.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-12 13:40:32 UTC
Permalink
[...]
Post by Peter J. Holzer
Die Warnung ist absolut berechtigt. (char *) und (unsigned char *) sind
keine kompatiblen Typen. char muss zwar die gleiche Repräsentation haben
wie entweder signed char oder unsigned char, ist aber ein dritter Typ,
der mit keinem der beiden kompatibel ist.
Das weiß ich und hatte es auch selbst geschrieben.

[...]
Post by Peter J. Holzer
Darüber, ob "differ in signedness" die bestmögliche Formulierung ist,
kann man streiten, aber ich halte es nicht für falsch: Die "signedness"
von "signed char" ist "signed", die von "unsigned char" ist "unsigned"
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Jedoch nicht, wenn man -funsigned-char gibt.
Der Compiler hat ja auch eine spezielle Warnung für inkompatible Typen
und Pointer-Typen.
Die verwendet er aber nicht, sondern lügt zur Vorzeichenbehaftung.
Post by Peter J. Holzer
Warnungen sollen auch vor unportablen Konstruktionen warnen. Auch wenn
bei deiner Implementation char unsigned ist, ist sie es bei anderen
vielleicht nicht.
Bei mir ist char signed, wird aber durch -funsigned-char unsigned.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-12 15:43:11 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Peter J. Holzer
Die Warnung ist absolut berechtigt. (char *) und (unsigned char *) sind
keine kompatiblen Typen. char muss zwar die gleiche Repräsentation haben
wie entweder signed char oder unsigned char, ist aber ein dritter Typ,
der mit keinem der beiden kompatibel ist.
Das weiß ich und hatte es auch selbst geschrieben.
[...]
Post by Peter J. Holzer
Darüber, ob "differ in signedness" die bestmögliche Formulierung ist,
kann man streiten, aber ich halte es nicht für falsch: Die "signedness"
von "signed char" ist "signed", die von "unsigned char" ist "unsigned"
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Jedoch nicht, wenn man -funsigned-char gibt.
Doch. Damit legst Du nur fest, welche Implementation Du verwendest.
Aus Sicht der Sprachdefinition sind "gcc -fsigned-char" und "gcc
-funsigned-char" zwei unterschiedliche Implementationen. Du verwendest
die, in der "char" unsigned ist. Andere verwenden die, in der "char"
signed ist. Die Warnung sagt Dir, dass es da ein potentielles
Portabilitätsproblem gibt.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-12 20:17:08 UTC
Permalink
Post by Peter J. Holzer
Post by Helmut Schellong
Post by Peter J. Holzer
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Es sind drei verschiedene Typen, aber stets nur zwei Signedness-es.
Post by Peter J. Holzer
Post by Helmut Schellong
Jedoch nicht, wenn man -funsigned-char gibt.
Doch. Damit legst Du nur fest, welche Implementation Du verwendest.
Aus Sicht der Sprachdefinition sind "gcc -fsigned-char" und "gcc
-funsigned-char" zwei unterschiedliche Implementationen. Du verwendest
die, in der "char" unsigned ist. Andere verwenden die, in der "char"
signed ist. Die Warnung sagt Dir, dass es da ein potentielles
Portabilitätsproblem gibt.
Die Compiler konterkariert sich selbst (postete ich bereits):

-funsigned-char
Let the type "char" be unsigned, like "unsigned char".

Each kind of machine has a default for what "char" should be. It
is either like "unsigned char" by default or like "signed char" by
default.

Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
But many programs have been written to use plain "char" and expect
it to be signed, or expect it to be unsigned, depending on the
machines they were written for. This option, and its inverse, let
you make such a program work with the opposite default.

The type "char" is always a distinct type from each of "signed
char" or "unsigned char", even though its behavior is always just
like one of those two.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-10-12 23:16:48 UTC
Permalink
Post by Helmut Schellong
Post by Peter J. Holzer
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Es sind drei verschiedene Typen, aber stets nur zwei Signedness-es.
Aber die von "char" ist eben nicht allgemein festgelegt. Für eine
bestimmte Implementation ist sie bekannt. Aber wenn Du portablen Code
schreibst, kannst Du Dich nicht darauf verlassen, dass sie bei einer
anderen Implementation gleich ist. Egal, ob char bei Dir signed oder
unsigned ist, es gibt *immer* eine andere Implementation, bei der es
genau anders herum ist. Und damit ist es immer so, dass sowohl beim
Mischen von char und unsigned char als auch beim Mischen von char und
signed char auf irgendeiner Implmentation die Signedness unterschiedlich
ist.

(Ich halte übrigens die Verwendung von -fsigned-char bzw.
-funsigned-char für einen Fehler. Die Optionen existieren, um Code
compilieren zu können, der fälschlicherweise von einer bestimmten
signedness von char ausgeht. Wenn man (nach 1989) neuen Code schreibt,
gibt es keinen Grund, diesen Fehler zu machen. Man schreibt einfach
char, signed char oder unsigned char (oder int8_t, uint8_t, etc.), je
nachdem, was inhaltlich sinnvoll ist, und bügelt die eigene
Schlampigkeit nicht mit einer Compileroption aus. Ich gebe, zu dass das
verlockend ist: Ich bin dieser Versuchung in den 80er-Jahren auch
erlegen. Aber Anfang der 90er Jahre habe ich nicht nur bei meinem
eigenen Code, sondern auch bei der Fehlersuche in anderer Leute Code
recht schnell bemerkt, dass das eine schlechte Idee ist)

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Claus Reibenstein
2016-10-13 06:34:04 UTC
Permalink
Post by Helmut Schellong
Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
Dem ist eigentlich nichts hinzuzufügen.

Gruß
Claus
G.B.
2016-10-13 07:53:43 UTC
Permalink
Post by Claus Reibenstein
Post by Helmut Schellong
Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
Dem ist eigentlich nichts hinzuzufügen.
Außer diesem Zusatz: Ein Programm, dass so massiv
Objekte von eingebauten Datentypen verwendet, nutzt
die Möglichkeit der Abstraktion zu wenig.

Der 1000fache Rummel entsteht nur durch genau einen (1) Effekt.
Man könnte auch sagen: durch einen 1000fachen Defekt des Quelltextes.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Helmut Schellong
2016-10-13 10:11:12 UTC
Permalink
Post by G.B.
Post by Claus Reibenstein
Post by Helmut Schellong
Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
Dem ist eigentlich nichts hinzuzufügen.
Außer diesem Zusatz: Ein Programm, dass so massiv
Objekte von eingebauten Datentypen verwendet, nutzt
die Möglichkeit der Abstraktion zu wenig.
Der 1000fache Rummel entsteht nur durch genau einen (1) Effekt.
Man könnte auch sagen: durch einen 1000fachen Defekt des Quelltextes.
Das Programm ist sehr gut systemisch strukturiert:
Wenn
#define byte char
gegeben ist: 0 Warnungen.

Wenn
#define byte unsigned char
gegeben ist: 1000 Warnungen.

Ich will aber, wie vorgeschlagen:
Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
unsigned char verwenden, weil mein Programm diese Signedness braucht.

Das geht aber nicht, weil dann 1000 Warnungen kommen.
Nur deshalb nehme ich -funsigned-char.
Damit wird char vorzeichenlos, und deshalb kann ich dann char
verwenden, und die Warnungen verschwinden.

Das Programm ist dann nicht ganz portabel:
Wenn ein Compiler -funsigned-char nicht hat, steh ich da, und muß
1000 Casts in mein Programm schreiben, was ich hasse.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Juergen Ilse
2016-10-13 11:07:46 UTC
Permalink
Hallo,
Post by Helmut Schellong
Wenn
#define byte char
gegeben ist: 0 Warnungen.
Wenn
#define byte unsigned char
gegeben ist: 1000 Warnungen.
Ideally, a portable program should always use "signed char" or
"unsigned char" when it depends on the signedness of an object.
unsigned char verwenden, weil mein Programm diese Signedness braucht.
Das geht aber nicht, weil dann 1000 Warnungen kommen.
Ein "String-Literal" ist aber laut standard kein "array of unsigned char"
sondern en !array of char". Das magst du bedauern, aber der Standard schreibt
das nun mal so vor. Du hast also an den Stellen wo du die Warnungen bekommst
in der Tat die Typen char und unsigned char vermischt und das der Compiler
dich deswegen warnt ist voellig in Ordnung.
Post by Helmut Schellong
Nur deshalb nehme ich -funsigned-char.
Das tut aber nicht das was du willst. char und unsigned char sind auch mit
dieser Option noch unterschiedliche Typen.
Post by Helmut Schellong
Damit wird char vorzeichenlos,
... aber noch immer nicht zum selben Typ wie char. Und daran, dass ein
string-Literal ein "array of char" und kein "array of unsigned char" ist,
aendert die Option auch nicht das geringste.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Helmut Schellong
2016-10-13 12:07:12 UTC
Permalink
Post by Juergen Ilse
Post by Helmut Schellong
Damit wird char vorzeichenlos,
... aber noch immer nicht zum selben Typ wie char. Und daran, dass ein
string-Literal ein "array of char" und kein "array of unsigned char" ist,
aendert die Option auch nicht das geringste.
Ja, heute ist das so, früher war das nicht so!
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Juergen Ilse
2016-10-13 14:15:22 UTC
Permalink
Hallo,
Post by Helmut Schellong
Post by Juergen Ilse
Post by Helmut Schellong
Damit wird char vorzeichenlos,
... aber noch immer nicht zum selben Typ wie char. Und daran, dass ein
string-Literal ein "array of char" und kein "array of unsigned char" ist,
aendert die Option auch nicht das geringste.
Ja, heute ist das so, früher war das nicht so!
Das war frueher auch schon so, nur hat der gcc diese (berechtigte) Warnung
noch unterlassen. Dass der Wortlaut der Warnungsmeldung in dem Punkt etwas
ungluecklich gewaehlt ist, hatten wir ja bereits erlaeutert.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Rainer Weikusat
2016-10-13 15:28:09 UTC
Permalink
Post by Juergen Ilse
Post by Helmut Schellong
Post by Juergen Ilse
Post by Helmut Schellong
Damit wird char vorzeichenlos,
... aber noch immer nicht zum selben Typ wie char. Und daran, dass ein
string-Literal ein "array of char" und kein "array of unsigned char" ist,
aendert die Option auch nicht das geringste.
Ja, heute ist das so, früher war das nicht so!
Das war frueher auch schon so, nur hat der gcc diese (berechtigte) Warnung
noch unterlassen.
Ich kann an dieser Warnung nichts 'berechtigtes' erkennen: Es handelt
sich um irgendjemandes vollkommen unrelevante Meinung bzgl 'welche
verbreiteten Hardware-Features halte ICH nicht fuer
wuenschenswert'. 'Wir' wissen bereits, das 'gcc-Leute'
vorzeichenbehaftete Zweierkomplement-Arithmetik fuer 'nicht
wuenschenswert' halten, vermutlich seit 195x. Interessiert laengst
keinen mehr, Diskussion beendet.
Peter J. Holzer
2016-10-13 19:11:31 UTC
Permalink
Post by Rainer Weikusat
Post by Juergen Ilse
Post by Helmut Schellong
Post by Juergen Ilse
Post by Helmut Schellong
Damit wird char vorzeichenlos,
... aber noch immer nicht zum selben Typ wie char. Und daran, dass ein
string-Literal ein "array of char" und kein "array of unsigned char" ist,
aendert die Option auch nicht das geringste.
Ja, heute ist das so, früher war das nicht so!
Das war frueher auch schon so, nur hat der gcc diese (berechtigte) Warnung
noch unterlassen.
Ich kann an dieser Warnung nichts 'berechtigtes' erkennen: Es handelt
sich um irgendjemandes vollkommen unrelevante Meinung bzgl 'welche
verbreiteten Hardware-Features halte ICH nicht fuer
wuenschenswert'.
Niemand wird gezwungen, -Wpointer-sign zu verwenden.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Thomas Koenig
2016-10-13 19:57:50 UTC
Permalink
Post by Rainer Weikusat
Post by Juergen Ilse
Das war frueher auch schon so, nur hat der gcc diese (berechtigte) Warnung
noch unterlassen.
Ich kann an dieser Warnung nichts 'berechtigtes' erkennen: Es handelt
sich um irgendjemandes vollkommen unrelevante Meinung bzgl 'welche
verbreiteten Hardware-Features halte ICH nicht fuer
wuenschenswert'. 'Wir' wissen bereits, das 'gcc-Leute'
vorzeichenbehaftete Zweierkomplement-Arithmetik fuer 'nicht
wuenschenswert' halten,
Care to elaborate?
Post by Rainer Weikusat
vermutlich seit 195x.
Naja, Fortran auf der IBM 704 hatte sign-magnitude. Ach Moment,
das war ja noch gar kein C. Was meinst du mit "seit 195x"?
Post by Rainer Weikusat
Interessiert laengst keinen mehr, Diskussion beendet.
Wie langwellig!
Peter J. Holzer
2016-10-13 20:53:28 UTC
Permalink
Post by Thomas Koenig
Post by Rainer Weikusat
Post by Juergen Ilse
Das war frueher auch schon so, nur hat der gcc diese (berechtigte) Warnung
noch unterlassen.
Ich kann an dieser Warnung nichts 'berechtigtes' erkennen: Es handelt
sich um irgendjemandes vollkommen unrelevante Meinung bzgl 'welche
verbreiteten Hardware-Features halte ICH nicht fuer
wuenschenswert'. 'Wir' wissen bereits, das 'gcc-Leute'
vorzeichenbehaftete Zweierkomplement-Arithmetik fuer 'nicht
wuenschenswert' halten,
Care to elaborate?
Rainers üblicher "Die Compilerbauer nehmen 'undefined behaviour' in
Fällen ernst, wo ich gerne definiertes Verhalten hätte und sind daher
Trotteln"-Rant.

Konkret ist Rainer der Meinung, dass Wraparound bei signed
Integer-Overflow das einzig sinnvolle Verhalten ist, und dass der GCC
das in allen Optimierungsstufen implementieren sollte.

Die GCC-Bauer hingegen freuen sich, dass ihnen der Standard erlaubt,
(i + 1 > i) zu (1) zu optimieren und machen davon gerne Gebrauch, wenn
man es nicht mit -fwrapv verbietet.
Post by Thomas Koenig
Post by Rainer Weikusat
vermutlich seit 195x.
Naja, Fortran auf der IBM 704 hatte sign-magnitude. Ach Moment,
das war ja noch gar kein C. Was meinst du mit "seit 195x"?
Er meint damit, dass die GCC-Entwickler immer schon realitätsfremde
Trotteln waren, die keine Ahnung vom Programmieren haben.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Rainer Weikusat
2016-10-13 22:06:38 UTC
Permalink
Post by Peter J. Holzer
Post by Thomas Koenig
Post by Rainer Weikusat
Post by Juergen Ilse
Das war frueher auch schon so, nur hat der gcc diese (berechtigte) Warnung
noch unterlassen.
Ich kann an dieser Warnung nichts 'berechtigtes' erkennen: Es handelt
sich um irgendjemandes vollkommen unrelevante Meinung bzgl 'welche
verbreiteten Hardware-Features halte ICH nicht fuer
wuenschenswert'. 'Wir' wissen bereits, das 'gcc-Leute'
vorzeichenbehaftete Zweierkomplement-Arithmetik fuer 'nicht
wuenschenswert' halten,
Care to elaborate?
Rainers üblicher "Die Compilerbauer nehmen 'undefined behaviour' in
Fällen ernst, wo ich gerne definiertes Verhalten hätte und sind daher
Trotteln"-Rant.
Konkret ist Rainer der Meinung, dass Wraparound bei signed
Integer-Overflow das einzig sinnvolle Verhalten ist, und dass der GCC
das in allen Optimierungsstufen implementieren sollte.
GCC implementiert hier gar nichts sondern er verhaelt sich
diesbezueglich immer noch so, wie es bereits der erste C-Compiler tat:
Er uebersetzt Integer-Additionen in die entsprechenden
Maschinenbefehle. Damit verhalten sich solche Additionen so, wie sie das
auf der gegebenen Hardware tun.
Post by Peter J. Holzer
Die GCC-Bauer hingegen freuen sich, dass ihnen der Standard erlaubt,
(i + 1 > i) zu (1) zu optimieren und machen davon gerne Gebrauch, wenn
man es nicht mit -fwrapv verbietet.
Diesbezueglich 'second thoughts' zu haben, hielt irgendein "GCC-Bauer"
(gemeint ist 'Landwirt') vor ein paar Jahren mal fuer eine gute
Idee. Mit einer an den Haaren herbeigezogenen Begruendung, die in
Widerspruch zu anderen Teilen der C-Norm steht und den Grund fuer die
diesbezueglichen Vagheiten, der heutzutage praktisch irrelevant ist,
ignoriert. Zur Erlangung von genau gar keinem Vorteil, denn diese
"Optimierung" basiert auf der Annahme, dass solcher Code keinen Sinn
haben sollte.
Post by Peter J. Holzer
Post by Thomas Koenig
Post by Rainer Weikusat
vermutlich seit 195x.
Naja, Fortran auf der IBM 704 hatte sign-magnitude. Ach Moment,
das war ja noch gar kein C. Was meinst du mit "seit 195x"?
Er meint damit, dass die GCC-Entwickler immer schon realitätsfremde
Trotteln waren, die keine Ahnung vom Programmieren haben.
Ich meine damit, dass 'Repraesentation vorzeichbehafteter Zahlen' heute
aufgrund der sogenannten 'normativen Kraft das Faktischen'
Zweierkomplement benutzt, dieser Zug ist also abgefahren.
Juergen Ilse
2016-10-13 22:48:57 UTC
Permalink
Hallo,
Post by Rainer Weikusat
Ich meine damit, dass 'Repraesentation vorzeichbehafteter Zahlen' heute
aufgrund der sogenannten 'normativen Kraft das Faktischen'
Zweierkomplement benutzt, dieser Zug ist also abgefahren.
... nur verweigert sich die Norm dieser "normativen Kraft des faktischen"
indem sie *ausdruecklich* auch Implementierungen mit Einerkomplement-
Darstellung fuer signed Integer-Typen zulaesst ...

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Peter J. Holzer
2016-10-14 12:12:57 UTC
Permalink
Post by Juergen Ilse
Hallo,
Post by Rainer Weikusat
Ich meine damit, dass 'Repraesentation vorzeichbehafteter Zahlen' heute
aufgrund der sogenannten 'normativen Kraft das Faktischen'
Zweierkomplement benutzt, dieser Zug ist also abgefahren.
... nur verweigert sich die Norm dieser "normativen Kraft des faktischen"
indem sie *ausdruecklich* auch Implementierungen mit Einerkomplement-
Darstellung fuer signed Integer-Typen zulaesst ...
Das ist hier allerdings nicht das Problem (eine Implementation, die auf
einem Prozessor mit Zweier-Komplement Einerkomplement-Arithmetik
implementiert, wäre wirklich pervers), sondern dass Overflow undefined
Behaviour ist.

Nach
i = INT_MAX;
i += 1;
ist also i nicht entweder INT_MIN (Zweierkomplement oder
Einerkomplement) oder -0 (Sign-Magnitude), sondern es kann irgendwas
passieren.

Eine weitere Möglichkeit ist z.B. ein Laufzeitfehler (gcc produziert
entsprechenden Code mit der Option -trapv, leider zumindest in Version
4.9 (Debian Stable) noch recht buggy). Im konkreten Fall könnte das der
Compiler sogar zur Compilezeit bemerken und die Compilation abbrechen.

Bei komplizierteren Ausdrücken ist noch mehr möglich.

Z.B.:

int ov(int i) {
return i + 1 < i;
}

Hier produziert der gcc mit -O2 Code, der immer 0 ausgibt (mit -Wall
bekommt man auch eine entsprechende Warnung).

Das ist standardkonform, denn es gibt zwei Fälle:

i < INT_MAX: Dann kann i + 1 berechnet werden und ist sicher größer als
i, das Ergebnis ist also 0.
i = INT_MAX: Dann passiert bei der Berechnung von i + 1 ein Overflow.
Also undefined behaviour, also ist jeder beliebige Wert
akzeptabel, also auch 0.

Das ist in diesem Fall eine Analyse, die der Optimizer durchführt. Aber
selbst ohne Optimizer könnte ein Compiler Code produzieren, der hier 0
zurückliefert. Stell Dir eine HW-Architektur vor, in der alle Register 64
Bit breit sind, und alle arithmetischen Operationen jeweils ganze
Register verwenden. Nur für Load-Store-Operationen gibt es
32-Bit-Operationen. Der C-Compiler implementiert aber I32LP64.

Dann wäre die natürlichste Art, ov zu compilieren sowas wie:

# parameter registers are pX
# return register r1
# auxiliary registers aX
ldi a1, 1
add a2, p1, a1
setlt r1, a2, p1
ret

oder? Aber da die Addition in 64-Bit ausgeführt wird, tritt hier kein
Overflow auf, a2 ist immer größer als p1, der Code prodoziert immer 0.

Um das von Rainer gewünschte Overflow-Verhalten zu erhalten, müsste der
Compiler zusätzlichen Code produzieren, der Bit 31 in Bits 32..63
repliziert.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Rainer Weikusat
2016-10-15 14:52:16 UTC
Permalink
"Peter J. Holzer" <hjp-***@hjp.at> writes:

[...]
Post by Peter J. Holzer
Bei komplizierteren Ausdrücken ist noch mehr möglich.
int ov(int i) {
return i + 1 < i;
}
Hier produziert der gcc mit -O2 Code, der immer 0 ausgibt (mit -Wall
bekommt man auch eine entsprechende Warnung).
i < INT_MAX: Dann kann i + 1 berechnet werden und ist sicher größer als
i, das Ergebnis ist also 0.
i = INT_MAX: Dann passiert bei der Berechnung von i + 1 ein Overflow.
Also undefined behaviour,
... falls dieser Ueberlauf per se eine 'exceptional condition' ist. Das
ist er aber auf Maschinenebene in vielen Faellen/ fast ausschliesslich
nicht. Ferner ist der Wert von i + 1 definiert als "Summe von i und
1". Diese Summe ist nicht notwendigerweise vom Typ 'int', sie muss nur
gegebenenfalls als solcher repraesentiert werden. Und damit waere man
bei

Otherwise, the new type is signed and the value cannot be
represented in it; either the result is implementation-defined
or an implementation-defined signal is raised.

was 'zufaelligerweise' genau das Verhalten von existierender Hardware
beschreibt: Entweder wird in dieser Situation eine Ausnahmenbehandlung
initiiert oder es kommt das dabei heraus, was dabei eben
herauskommt. Auf dieser Basis koennten die gcc-Farmer immer noch
beschliessen, das ihnen praktische Erwaegungen egal sind und ihr
Lieblingsergebniss 42 ist.
Post by Peter J. Holzer
also ist jeder beliebige Wert akzeptabel, also auch 0.
Also ist durch die C-Norm nichts bestimmtes vorgeschrieben. Inwiefern
Code, der hoechstwahrscheinlich eine Ueberlaufpruefung durchfuehren
sollte, und in dieser Form seit anno Tobak auch dafuer verwendet wurde,
einfach unter den Tisch fallen zu lassen, akzeptabel ist, weil niemand
das ausdruecklich verboten hat, waere eine vollkommen andere Frage.

Die C-Norm verlangt naemlich keineswegs, dass das reale Verhalten in
Situation, fuer die die C-Norm kein Verhalten definiert, maximal
bloedsinnig/ gefaehrlich ist.
Peter J. Holzer
2016-10-15 16:44:25 UTC
Permalink
Post by Rainer Weikusat
Post by Peter J. Holzer
Bei komplizierteren Ausdrücken ist noch mehr möglich.
int ov(int i) {
return i + 1 < i;
}
Hier produziert der gcc mit -O2 Code, der immer 0 ausgibt (mit -Wall
bekommt man auch eine entsprechende Warnung).
i < INT_MAX: Dann kann i + 1 berechnet werden und ist sicher größer als
i, das Ergebnis ist also 0.
i = INT_MAX: Dann passiert bei der Berechnung von i + 1 ein Overflow.
Also undefined behaviour,
... falls dieser Ueberlauf per se eine 'exceptional condition' ist.
Und was eine 'exceptional condition' ist, steht gleich danach in
Klammern:

| (that is, if the result is not mathematically defined or not in the
| range of representable values for its type)

Man muss schon sehr selektiv lesen, um das zu übersehen und sich statt
Post by Rainer Weikusat
Das ist er aber auf Maschinenebene in vielen Faellen/ fast
ausschliesslich nicht.
Das ist unerheblich. Der (mathematische) Wert von INT_MAX + 1 ist nicht
im Typ int repräsentierbar, damit ist das eine /exceptional condition/.
Nirgends steht, dass die Hardware dafür irgendwas besonderes machen
muss.
Post by Rainer Weikusat
Ferner ist der Wert von i + 1 definiert als "Summe von i und
1". Diese Summe ist nicht notwendigerweise vom Typ 'int',
/6.3.1.8 Usual arithmetic conversions/ ist ganz eindeutig. Mit zwei
Operanden vom Typ int, ist das Ergebnis des Operators "+" auch wieder
vom Typ int.

(Wenn Du übrigens recht hättest, wäre an ((i + 1 < i) == 0) schon
überhaupt nichts auszusetzen, denn dann könnte der Ausdruck in long long
oder double ausgewertet werden und würde wieder stimmen)
Post by Rainer Weikusat
Die C-Norm verlangt naemlich keineswegs, dass das reale Verhalten in
Situation, fuer die die C-Norm kein Verhalten definiert, maximal
bloedsinnig/ gefaehrlich ist.
Nein, aber sie verlangt auch nicht, dass ein Compiler das tut, was Du
gerade für sinnvoll erachtest. Die C-Norm lässt der Implementation große
Freiheiten. Meiner Meinung nach zu große, und das ist einer der Gründe,
warum ich C nur im Notfall verwende. Aber wenn man C verwendet, muss man
halt mit diesen Freiheiten leben - oder Compiler verwenden, die kein
maximal blödsinnig/gefährliches Verhalten zeigen.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Rainer Weikusat
2016-10-15 17:34:03 UTC
Permalink
Post by Peter J. Holzer
Post by Rainer Weikusat
Post by Peter J. Holzer
Bei komplizierteren Ausdrücken ist noch mehr möglich.
int ov(int i) {
return i + 1 < i;
}
Hier produziert der gcc mit -O2 Code, der immer 0 ausgibt (mit -Wall
bekommt man auch eine entsprechende Warnung).
i < INT_MAX: Dann kann i + 1 berechnet werden und ist sicher größer als
i, das Ergebnis ist also 0.
i = INT_MAX: Dann passiert bei der Berechnung von i + 1 ein Overflow.
Also undefined behaviour,
... falls dieser Ueberlauf per se eine 'exceptional condition' ist.
Und was eine 'exceptional condition' ist, steht gleich danach in
| (that is, if the result is not mathematically defined or not in the
| range of representable values for its type)
Man muss schon sehr selektiv lesen, um das zu übersehen und sich statt
Eine parenthetische Bemerkung ist keine Definition.
Post by Peter J. Holzer
Post by Rainer Weikusat
Das ist er aber auf Maschinenebene in vielen Faellen/ fast
ausschliesslich nicht.
Das ist unerheblich. Der (mathematische) Wert von INT_MAX + 1 ist nicht
im Typ int repräsentierbar,
Das ist unerheblich, denn der "mathematische Wert von INT_MAX + 1" fuer
eine Operation + die fuer die Menge der ganzen Zahlen definiert ist,
wird hier nicht berechnet. Das ist lediglich ein Wert, der nach
irgendjemandes Ansicht anstelle dessen, der berechnet wird, eigentlich
berechnet werden sollte.

[...]
Post by Peter J. Holzer
Post by Rainer Weikusat
Ferner ist der Wert von i + 1 definiert als "Summe von i und
1". Diese Summe ist nicht notwendigerweise vom Typ 'int',
| sie muss nur gegebenenfalls als solcher repraesentiert werden.
Post by Peter J. Holzer
/6.3.1.8 Usual arithmetic conversions/ ist ganz eindeutig. Mit zwei
Operanden vom Typ int, ist das Ergebnis des Operators "+" auch wieder
vom Typ int.
Wie im restaurierten Text ersichtlich hatte ich dem durchaus nicht
widersprochen: Falls man annimmt, die Definitionsmenge von + sei nicht
ein C Typ und INT_MAX + 1 koenne deswegen ein Ergebnis haben, das als
C int nicht darstellbar ist, hat man hier ein 'Zwischenergebnis' welches
als lezten Teil der Berechnung nach int konvertiert werden muss. Und
dafuer gibt es Regeln von denen ich eine zitiert hatte.

[Compiler "weg-optimiert" Ueberlaufpruefung]
Post by Peter J. Holzer
Post by Rainer Weikusat
Die C-Norm verlangt naemlich keineswegs, dass das reale Verhalten in
Situation, fuer die die C-Norm kein Verhalten definiert, maximal
bloedsinnig/ gefaehrlich ist.
Nein, aber sie verlangt auch nicht, dass ein Compiler das tut, was Du
gerade für sinnvoll erachtest.
Es ist Dir vollkommen freigestellt, Ueberlaufpruefungen in
existierendem Code fuer "nicht sinnvoll" zu halten. Aber bitte mit
offenem Harnisch.
Helmut Schellong
2016-10-15 20:26:20 UTC
Permalink
[...]
Post by Peter J. Holzer
Post by Rainer Weikusat
Das ist er aber auf Maschinenebene in vielen Faellen/ fast
ausschliesslich nicht.
Das ist unerheblich. Der (mathematische) Wert von INT_MAX + 1 ist nicht
im Typ int repräsentierbar, damit ist das eine /exceptional condition/.
int main(void)
{
printf("%d %u %d %u\n%d %u %d %u\n",
INT_MAX, INT_MAX, INT_MIN, INT_MIN,
INT_MAX+1,INT_MAX+1, INT_MAX+2,INT_MAX+2);
}

2147483647 2147483647 -2147483648 2147483648
-2147483648 2147483648 -2147483647 2147483649

In der Realität ist solch alles definiert, vorhersagbar,
reproduzierbar und Exceptions gibt es hier nicht.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
G.B.
2016-10-16 08:46:21 UTC
Permalink
Post by Helmut Schellong
In der Realität ist solch alles definiert, vorhersagbar,
reproduzierbar und Exceptions gibt es hier nicht.
In deiner Realität?

Sobald "Realität" definiert werden kann als das, was zu den eigenen
Voraussetzungen passt, und nicht etwa sich auf Statistik stützen muss,
formale Vorgaben beachten, oder nach einer Projektumschau,
wird diese besonders definierte Umgebung hinreichende Vorhersagbarkeit
erzeugen.
Freilich nicht aus dem Quelltext allein. Denn da steht weiterhin
INT_MAX + 1.
Die korrekte Verwendung dieses Ausdrucks der eigen-realen
Implementierung mag Vorhersagbarkeit bedeuten,
die Programmierung mag sogar mit Bedacht int-Rückgabewerte auf
"sonderbare" negative Werte überprüfen, oder, wer weiß, vielleicht
Routinen installiert haben, die allfällige Ausnahmen sinnvoll behandeln.
Nur, warum dann sich beschweren, wenn eine Norm, also etwas
ohne Implementierungs-bezogene Selbstgenügsamkeit, die sich der
Voraussage des Verhaltens von "INT_MAX + 1" enthält und dadurch
Offenheiten für Implementierer entstehen lässt, die in einer
nicht gesonderten Realität, vielleicht auch aus Rücksicht auf
hysterische Sultaninen, eine andere Wahl getroffen hat?

Freilich beseitigt beides in einer anderen Realität immer noch nicht
die Dauerprobleme, die aus char* oder i++ am Ende der Wertmenge
entstehen.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Helmut Schellong
2016-10-16 10:21:34 UTC
Permalink
Post by G.B.
Post by Helmut Schellong
In der Realität ist solch alles definiert, vorhersagbar,
reproduzierbar und Exceptions gibt es hier nicht.
In deiner Realität?
Ja und nein.
Realität ist das, was ich seit 1987 privat erlebe, und was ich bis
zu meinem Lebensende erleben werde (im Zusammenhang).

Mit mir werden diese Realität mindestens 99% aller anderen
Computernutzer ebenfalls erleben.
Post by G.B.
Sobald "Realität" definiert werden kann als das, was zu den eigenen
Voraussetzungen passt, und nicht etwa sich auf Statistik stützen muss,
formale Vorgaben beachten, oder nach einer Projektumschau,
wird diese besonders definierte Umgebung hinreichende Vorhersagbarkeit
erzeugen.
Realität ist für mich das, was ich tatsächlich erlebte und erlebe.
Post by G.B.
Freilich nicht aus dem Quelltext allein. Denn da steht weiterhin
INT_MAX + 1.
Die korrekte Verwendung dieses Ausdrucks der eigen-realen
Implementierung mag Vorhersagbarkeit bedeuten,
die Programmierung mag sogar mit Bedacht int-Rückgabewerte auf
"sonderbare" negative Werte überprüfen, oder, wer weiß, vielleicht
Routinen installiert haben, die allfällige Ausnahmen sinnvoll behandeln.
Nur, warum dann sich beschweren, wenn eine Norm, also etwas
ohne Implementierungs-bezogene Selbstgenügsamkeit, die sich der
Voraussage des Verhaltens von "INT_MAX + 1" enthält und dadurch
Offenheiten für Implementierer entstehen lässt, die in einer
nicht gesonderten Realität, vielleicht auch aus Rücksicht auf
hysterische Sultaninen, eine andere Wahl getroffen hat?
Derjenige Anteil des Standards, der auf die denkbar exotischste Hardware
abstellt, die eventuell und theoretisch mal existieren könnte, und zu der
der Standard dann auch paßte, ist für mich zum Lesen eher uninteressant, da
ich sicher weiß, daß ich mit solcher Hardware nie umgehen werde.

Das heißt auch, es ist unprofessionell, sich mit Dingen zu befassen und
Zeit dafür zu investieren, die einen nie betreffen werden.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-16 12:08:19 UTC
Permalink
Post by Helmut Schellong
Realität ist das, was ich seit 1987 privat erlebe, und was ich bis
zu meinem Lebensende erleben werde (im Zusammenhang).
D.h. du bestreitest Realität abseits deiner eigenen Erfahrungen?
Du wirst nicht viele Leute finden, die damit übereinstimmen :-)
Stefan Reuther
2016-10-16 09:06:06 UTC
Permalink
Post by Rainer Weikusat
[...]
Post by Peter J. Holzer
Post by Rainer Weikusat
Das ist er aber auf Maschinenebene in vielen Faellen/ fast
ausschliesslich nicht.
Das ist unerheblich. Der (mathematische) Wert von INT_MAX + 1 ist nicht
im Typ int repräsentierbar, damit ist das eine /exceptional condition/.
int main(void)
{
printf("%d %u %d %u\n%d %u %d %u\n",
INT_MAX, INT_MAX, INT_MIN, INT_MIN,
INT_MAX+1,INT_MAX+1, INT_MAX+2,INT_MAX+2);
}
2147483647 2147483647 -2147483648 2147483648
-2147483648 2147483648 -2147483647 2147483649
In der Realität ist solch alles definiert, vorhersagbar,
reproduzierbar und Exceptions gibt es hier nicht.
Du meinst, das sei alles "definiert, vorhersagbar, reproduzierbar" und
im nächsten Teilthread beschwerst du dich, dass der Compiler für
'unsigned char' anderen Code generiert als für 'char'? Merkste selber, oder?

Die Tatsache, dass ein bestimmtes Sprachkonstrukt undefiniertes
Verhalten hat, erlaubt einem Compiler, bestimmte Optimierungen
durchzuführen, die sich darauf verlassen, dass der Programmierer dieses
Sprachkonstrukt nicht nutzt. Gerade beim Überlaufverhalten gibt es genug
Gründe für einen Compiler, das zu tun. Die kannst du nicht alle
vorhersagen, die fehlt nur vielleicht die Phantasie dafür.

Ich habe beispielsweise schon mit Architekturen gearbeitet, wo der
Assemblerbefehl "Addition mit Saturierung" eine Parallelisierung mit
anderen Assemblerbefehlen erlaubte, der Assemblerbefehl "Addition mit
Wraparound-wie-wir-ihn-kennen" hingegen nicht. Ich würde von einem
anständigen Compiler erwarten, dass er das nutzt.


Stefan
Helmut Schellong
2016-10-16 17:05:23 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
2147483647 2147483647 -2147483648 2147483648
-2147483648 2147483648 -2147483647 2147483649
In der Realität ist solch alles definiert, vorhersagbar,
reproduzierbar und Exceptions gibt es hier nicht.
Du meinst, das sei alles "definiert, vorhersagbar, reproduzierbar" und
im nächsten Teilthread beschwerst du dich, dass der Compiler für
'unsigned char' anderen Code generiert als für 'char'? Merkste selber, oder?
Das sind zwei gänzlich unterschiedliche Probleme.
Andere Compiler als der icc scheinen analytisch nicht ganz perfekt
zu sein. Der icc ist wohl anscheinend perfekt.

Der Ausdruck INT_MAX+1 befindet sich auf einer anderen Problemebene.
Diese Ebene ist das reale Verhalten von Hardware.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-16 12:55:28 UTC
Permalink
Post by Peter J. Holzer
Bei komplizierteren Ausdrücken ist noch mehr möglich.
int ov(int i) {
return i + 1 < i;
}
Hier produziert der gcc mit -O2 Code, der immer 0 ausgibt (mit -Wall
bekommt man auch eine entsprechende Warnung).
Noch ein bisschen komplizierter:

Wenn man

int ov(int i, int j) {
return i+1 < j;
}

aufruft mit

if (ov(i,i)) {
}

dann kann ein moderner Compiler das z.B. per LTO komplett wegoptimieren,
auch wenn ov in irgendeiner Library steht.

LTO ist einer der Gründe, warum viele beim ersten Blick dämliche
Optimierungen durchaus Sinn ergeben - weil der Programmierer den
"einfachen" Fall kaum bemerken kann, weil der in einem ganz
anderen Teil des Quelltextes steht.
Rainer Weikusat
2016-10-14 12:55:13 UTC
Permalink
Post by Juergen Ilse
Post by Rainer Weikusat
Ich meine damit, dass 'Repraesentation vorzeichbehafteter Zahlen' heute
aufgrund der sogenannten 'normativen Kraft das Faktischen'
Zweierkomplement benutzt, dieser Zug ist also abgefahren.
... nur verweigert sich die Norm dieser "normativen Kraft des faktischen"
indem sie *ausdruecklich* auch Implementierungen mit Einerkomplement-
Darstellung fuer signed Integer-Typen zulaesst ...
Sowie sign-and-magnitude. Das ist in Grenzen sinnvoll, weil solche
Hardware existiert (oder wenigstens mal existierte) und es gibt keinen
Grund, warum man C-Implementierungen, die direkt auf der Hardware
aufsetzen, fuer solche unmoeglich machen sollte. Das aendert aber nichts
an der Tatsache, dass das unterschiedliche Ansaetze sind, mit denen
Leute in der Vergangenheit experimentiert haben, um den geeignetsten
herauszufinden. Ob das geschehen ist, darueber koennte man diskutieren,
aber das aendert nichts an der Tatsache, dass 2-er Komplementent der
Normalfall ist, und alles andere 'exotische Hardware' (von der sogar die
meisten sogenannten Programmierer nicht mal wissen, dass sie ueberhaupt
existiert).

Anders formuliert: Warum handhaben auch ARM-Prozessoren mittlerweile
alignment traps mit Hardware? Antwort: Chips kann man aendern. Bei
PehZeh-Programmierern ist das aussichtslos.
Thomas Koenig
2016-10-14 18:33:38 UTC
Permalink
Post by Rainer Weikusat
Post by Peter J. Holzer
Die GCC-Bauer hingegen freuen sich, dass ihnen der Standard erlaubt,
(i + 1 > i) zu (1) zu optimieren und machen davon gerne Gebrauch, wenn
man es nicht mit -fwrapv verbietet.
Diesbezueglich 'second thoughts' zu haben, hielt irgendein "GCC-Bauer"
(gemeint ist 'Landwirt') vor ein paar Jahren mal fuer eine gute
Idee. Mit einer an den Haaren herbeigezogenen Begruendung, die in
Widerspruch zu anderen Teilen der C-Norm steht
Zu welchen Teilen?

Wenn deine Begründung stichhaltig ist, dann schreib einen PR
(oder einen DR, wenn es ein bisschen schwrieriger ist).
Post by Rainer Weikusat
und den Grund fuer die
diesbezueglichen Vagheiten, der heutzutage praktisch irrelevant ist,
ignoriert.
Kein C-Compiler für die Unisys 2200-Serie? Och Menno.
Rainer Weikusat
2016-10-15 14:59:58 UTC
Permalink
[...]
Post by Thomas Koenig
Post by Rainer Weikusat
und den Grund fuer die
diesbezueglichen Vagheiten, der heutzutage praktisch irrelevant ist,
ignoriert.
Kein C-Compiler für die Unisys 2200-Serie? Och Menno.
Ich halte es fuer ausgeschlossen, dass ich jemals etwas in C
programmieren werde, das auf einen solchen System ausgefuehrt werden
wird, ohne das es von Anfang an dafuer entwickelt wurde. Und die weitaus
groesser Gruppe der "Wir muessen das in C# implementieren denn das habe
ich im Astrophysik-Studium nebenher gelernt und noch eine
Programmiersprache ... das waere echt Zu Kompliziert!!1"-Leute wissen
nicht mal um dessen Existenz.
Thomas Koenig
2016-10-15 17:53:15 UTC
Permalink
Post by Rainer Weikusat
[...]
Post by Thomas Koenig
Post by Rainer Weikusat
und den Grund fuer die
diesbezueglichen Vagheiten, der heutzutage praktisch irrelevant ist,
ignoriert.
Kein C-Compiler für die Unisys 2200-Serie? Och Menno.
Ich halte es fuer ausgeschlossen, dass ich jemals etwas in C
programmieren werde, das auf einen solchen System ausgefuehrt werden
wird, ohne das es von Anfang an dafuer entwickelt wurde.
Mag sein, dass du gerne und grundsätzlich unportablen Code schreibst.
Du bist aber - bei allem Respekt - nicht das Maß aller Dinge.
Andere Leute wollen gerne etwas anderes :-)

Eine Einer-Komplement-Maschine mit 36-bit-Wörtern hat doch was.
Hmm... char wäre vermutlich unsigned auf so einer Maschine,
für signed char müsste man sich ein bisschen verbiegen.

Wenigstens kann man da mit "float" etwas mehr anfangen, 27 bit
Mantisse taugt schon deutlich mehr als die 23/24 von IEEE.
Peter J. Holzer
2016-10-15 18:27:17 UTC
Permalink
Post by Thomas Koenig
Post by Rainer Weikusat
Post by Thomas Koenig
und den Grund fuer die diesbezueglichen Vagheiten, der heutzutage
praktisch irrelevant ist, ignoriert.
Kein C-Compiler für die Unisys 2200-Serie? Och Menno.
Ich halte es fuer ausgeschlossen, dass ich jemals etwas in C
programmieren werde, das auf einen solchen System ausgefuehrt werden
wird, ohne das es von Anfang an dafuer entwickelt wurde.
Mag sein, dass du gerne und grundsätzlich unportablen Code schreibst.
Du bist aber - bei allem Respekt - nicht das Maß aller Dinge.
Andere Leute wollen gerne etwas anderes :-)
Ich gebe zu, um Systeme mit Wortlängen, die keine 2er-Potenzen sind,
mache ich mir auch keine großen Gedanken mehr. Wenn's leicht geht,
unterstütze ich sie, wenn's nicht leicht geht, kommt an passender Stelle
halt ein assert() hin, dann soll sich die Person drum kümmern, die das
System betreibt.

Undefined behavior hingegen versuche ich um jeden Preis zu vermeiden.
Denn da es eben undefiniert ist, kann es sich auf jede beliebige Art
äußern, und es ist unmöglich, zuverlässige Tests dafür zu schreiben (es
kann in jedem Test genau das machen, was man möchte und im Produktivcode
doch was anderes).
Post by Thomas Koenig
Eine Einer-Komplement-Maschine mit 36-bit-Wörtern hat doch was.
Hmm... char wäre vermutlich unsigned auf so einer Maschine,
für signed char müsste man sich ein bisschen verbiegen.
Warum das? 9-Bit-Bytes mit Einer-Komplement ergibt einen Range von
±255. Das hätte sogar den Charme, dass alle Bytes, die man von einem
Socket oder portablen File liest, nicht-negativ sind. Nur Bytes, die man
von einem OS-spezifischen File liest, können negativ sein.
Post by Thomas Koenig
Wenigstens kann man da mit "float" etwas mehr anfangen, 27 bit
Mantisse taugt schon deutlich mehr als die 23/24 von IEEE.
Yup. Dem Vernehmen nach (ich bin ein bisschen zu jung dafür) haben
etliche Leute beim Übergang von 36-bit float auf 32-bit float geflucht
(und sind dann auf 64-bit double umgestiegen). Offenbar liegt die Grenze
für einige Real-World-Probleme gerade dazwischen: 27 Bit Mantisse sind
gerade noch ausreichend, 24 Bit gerade zuwenig.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Thomas Koenig
2016-10-16 12:11:09 UTC
Permalink
Post by Peter J. Holzer
Post by Thomas Koenig
Eine Einer-Komplement-Maschine mit 36-bit-Wörtern hat doch was.
Hmm... char wäre vermutlich unsigned auf so einer Maschine,
für signed char müsste man sich ein bisschen verbiegen.
Warum das? 9-Bit-Bytes mit Einer-Komplement ergibt einen Range von
±255. Das hätte sogar den Charme, dass alle Bytes, die man von einem
Socket oder portablen File liest, nicht-negativ sind. Nur Bytes, die man
von einem OS-spezifischen File liest, können negativ sein.
Die Maschinensprache der 1100 und 2200 - Serien hat nur unsigned
quarter word - (9 bit) - Instruktionen. Für die Implementierung
von signed müsste man da einfach mehr Aufwand treiben.
Peter J. Holzer
2016-10-16 13:20:39 UTC
Permalink
Post by Thomas Koenig
Post by Peter J. Holzer
Post by Thomas Koenig
Eine Einer-Komplement-Maschine mit 36-bit-Wörtern hat doch was.
Hmm... char wäre vermutlich unsigned auf so einer Maschine,
für signed char müsste man sich ein bisschen verbiegen.
Warum das? 9-Bit-Bytes mit Einer-Komplement ergibt einen Range von
±255. Das hätte sogar den Charme, dass alle Bytes, die man von einem
Socket oder portablen File liest, nicht-negativ sind. Nur Bytes, die man
von einem OS-spezifischen File liest, können negativ sein.
Die Maschinensprache der 1100 und 2200 - Serien hat nur unsigned
quarter word - (9 bit) - Instruktionen. Für die Implementierung
von signed müsste man da einfach mehr Aufwand treiben.
Ok. Dann würde man natürlich char unsigned machen. Aber das folgt ja
nicht zwinged aus "Einer-Komplement-Maschine mit 36-bit-Wörtern" (Wir
hatten von 1978 bis 1991 eine 1100 (im Lauf der Jahre von /81 auf /83
upgegradet). Aber das war vor meiner Zeit, daher kenne ich das Ding nur
aus Erzählungen der älteren Kolleg(inn)en.)

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Peter J. Holzer
2016-10-16 13:23:17 UTC
Permalink
Post by Thomas Koenig
Post by Peter J. Holzer
Post by Thomas Koenig
Eine Einer-Komplement-Maschine mit 36-bit-Wörtern hat doch was.
Hmm... char wäre vermutlich unsigned auf so einer Maschine,
für signed char müsste man sich ein bisschen verbiegen.
Warum das? 9-Bit-Bytes mit Einer-Komplement ergibt einen Range von
±255. Das hätte sogar den Charme, dass alle Bytes, die man von einem
Socket oder portablen File liest, nicht-negativ sind. Nur Bytes, die man
von einem OS-spezifischen File liest, können negativ sein.
Die Maschinensprache der 1100 und 2200 - Serien hat nur unsigned
quarter word - (9 bit) - Instruktionen. Für die Implementierung
von signed müsste man da einfach mehr Aufwand treiben.
Ok. Dann würde man natürlich char unsigned machen. Aber das folgt ja
nicht zwinged aus "Einer-Komplement-Maschine mit 36-bit-Wörtern" (Wir
hatten von 1980 bis 1991 eine 1100 (im Lauf der Jahre von /81 auf /83
upgegradet). Aber das war vor meiner Zeit, daher kenne ich das Ding nur
aus Erzählungen der älteren Kolleg(inn)en.)

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-10-13 22:18:49 UTC
Permalink
Post by Peter J. Holzer
Die GCC-Bauer hingegen freuen sich, dass ihnen der Standard erlaubt,
(i + 1 > i) zu (1) zu optimieren und machen davon gerne Gebrauch, wenn
man es nicht mit -fwrapv verbietet.
Der Compiler sollte m.E. so nicht optimieren.
Bei mir tut er das auch nicht bei -O1:

int f(unsigned u, int i) { return (u+1>u)+(i+1>i); }

lea eax, [rdi+1] # tmp97,
cmp edi, eax # u, tmp97
setb al #, tmp98
movzx eax, al # tmp98, tmp98
lea edx, [rsi+1] # tmp100,
cmp esi, edx # i, tmp100
setl dl #, tmp101
movzx edx, dl # tmp101, tmp101
add eax, edx # tmp96, tmp101
ret
-O3:
lea eax, [rdi+1] # tmp91,
cmp edi, eax # u, tmp91
setb al #, <retval>
movzx eax, al # <retval>, <retval>
add eax, 1 # <retval>,
ret

Der Prozessor hat keine signed-Addition oder signed-Subtraktion.
Er macht das alles unsigned modulo, jedoch die Flags zeigen an,
was vorliegt.
setb = set_below below,above ist unsigned
setl = set_less less,greater ist signed

Die return-Werte sind unterschiedlich zwischen -O1 und -O3.

Bei INT_MAX+1 entsteht (-INT_MAX-1) bei 2er-Komplement.
Es entsteht INT_MIN.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
G.B.
2016-10-13 11:39:44 UTC
Permalink
Post by Helmut Schellong
Wenn ein Compiler -funsigned-char nicht hat, steh ich da, und muß
1000 Casts in mein Programm schreiben, was ich hasse.
Genau das zu isolieren ist Abstraktion eine Möglichkeit.

#include <string.h>

struct Text {
unsigned char *_content;
};

#define chartyp char
#define PCONTENT(s) ((chartyp*)s->_content)
#define CONTENT(s) ((chartyp*)s._content)

int fp(struct Text* t) {
return strlen(PCONTENT(t));
}

int f(struct Text t) {
return strlen(CONTENT(t));
}

int g(char* s) {
return strlen(s);
}

int cl(unsigned char t1[]) {
struct Text t0 = { t1 };
int fpl = fp(&t0);
int fl = f(t0);
int gl = g(t1);

return (fpl + fl + gl) / 3;
}

int main(int argc, char* argv[])
{
return cl(argv[1]);
}

f und g werden identisch übersetzt, fp muss zusätzlich noch
über den Zeiger auspacken. Meine compiler sind bei f und fp
ziemlich schweigsam, was die Vorzeichen angeht, was nicht
überrascht. Man könnte auch PCHARGH und CHARGH als Namen für
die Makros wählen.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Stefan Reuther
2016-10-15 09:28:09 UTC
Permalink
Post by Peter J. Holzer
Darüber, ob "differ in signedness" die bestmögliche Formulierung ist,
kann man streiten, aber ich halte es nicht für falsch: Die "signedness"
von "signed char" ist "signed", die von "unsigned char" ist "unsigned"
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Fast. Der Denkfehler, dem Helmut unterliegt (und den deine Formulierung
nicht ausräumt) ist, dass 'char' je nach Implementation entweder der
gleiche Typ wie 'signed char' oder 'unsigned char' ist. Aber das ist
nicht so, auch mit '-funsigned-char' ist 'char' ein von 'unsigned char'
verschiedener Typ, sie haben nur den gleichen Wertebereich und die
gleiche Repräsentation. Genauso wie 'int' und 'long' auf i386 gleichen
Wertebereich und Repräsentation haben, aber verschiedene Typen sind.

Insofern warnt der Compiler hier nicht vor einem Portabilitätsproblem,
sondern vor einem realen Typproblem.


Stefan
Peter J. Holzer
2016-10-15 11:41:17 UTC
Permalink
Post by Stefan Reuther
Post by Peter J. Holzer
Darüber, ob "differ in signedness" die bestmögliche Formulierung ist,
kann man streiten, aber ich halte es nicht für falsch: Die "signedness"
von "signed char" ist "signed", die von "unsigned char" ist "unsigned"
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Fast. Der Denkfehler, dem Helmut unterliegt (und den deine Formulierung
nicht ausräumt) ist, dass 'char' je nach Implementation entweder der
gleiche Typ wie 'signed char' oder 'unsigned char' ist.
Es ist immer gefährlich, darüber zu spekulieren, was jemand denkt oder
nicht denkt. Da Helmut mehrmals geschrieben hat, dass er sich dessen
bewusst ist, dass es verschiedene Typen sind, glaube ich aber, dass Du
unrecht hast. Er glaubt nicht, dass es der gleiche Typ ist, aber er ist
der Meinung, dass »char« die gleiche »signedness« hat wie »unsigned
char« und daher die Warnung falsch ist.

Und für die konkrete Implementation, die er verwendet (gcc
-funsigned-char) hat er recht: Sowohl char als auch unsigned char sind
unsigned.

Aber das ist eben nicht das, wovor der Compiler hier warnen will: Er
sagt nicht, "Vorsicht, ich erzeuge jetzt gerade Code, der vielleicht
nicht tut, was Du willst", sondern "Vorsicht, der Source-Code den Du
geschrieben hast, wird auf vielen Implementationen vielleicht nicht das
tun, was Du willst".
Post by Stefan Reuther
Aber das ist nicht so, auch mit '-funsigned-char' ist 'char' ein von
'unsigned char' verschiedener Typ, sie haben nur den gleichen
Wertebereich und die gleiche Repräsentation. Genauso wie 'int' und
'long' auf i386 gleichen Wertebereich und Repräsentation haben, aber
verschiedene Typen sind.
Exzellentes Beispiel. Wollte ich auch schon bringen ;-)

Auf ILP32-Architekturen (wie z.B. i386) haben int und long die gleiche
Repräsentation. Beide sind 32 Bit, beide verwende die gleiche
Darstellung für negative Zahlen, beide haben das gleiche Alignment.

Es macht für den generierten Code keinen Unterschied, ob man int oder
long verwendet. Ein Programmierer könnte eine Warnung über "inkompatible
Typen" (oder gar "Typen verschiedener Größe") für unnötig oder gar
falsch halten: Denn die beiden Typen haben doch offensichtlich die
gleiche Größe und sie verhalten sich in jeder Hinsicht gleich. Wozu also
die Warnung?

Weil der Standard eben nicht garantiert, dass sich int und long gleich
verhalten und es tatsächlich Architekturen gibt (und die sogar recht
häufig sind), wo das nicht der Fall ist.
Post by Stefan Reuther
Insofern warnt der Compiler hier nicht vor einem Portabilitätsproblem,
sondern vor einem realen Typproblem.
Ich sehe hier den Widerspruch nicht. Es ist ein reales Typproblem, ja.
aber es ist deshalb real, weil es ein Portabilitätsproblem ist. Auf der
Architektur, für die der Compiler gerade übersetzt, existiert das
Problem nicht, aber es existiert auf anderen.

(Es gibt auch reale Typprobleme, die keine Portabilitätsprobleme sind:
int und float können m.M.n auf keinem System die gleiche Repräsentation
haben[1], wenn man die vermischt, hat man also immer ein Problem. Umgekehrt
gibt es Portabilitätsprobleme, die keine Typprobleme sind. Und es gibt
wahrscheinlich Typprobleme, die nicht real sind: Dinge, die der Standard
nicht garantiert, die aber auf jeder existierenden oder auch nur
plausiblen Architektur der Fall sind - sowas würde ich ein theoretisches
Typproblem nennen.)


[1] Oder doch? Was ist, wenn man die Bits des Exponenten als
Padding-Bits ansieht? Dann blieben die Mantisse und das Vorzeichen
über, und das könnte eine Sign-Magnitude-Darstellung sein, wenn die
Mantisse denormalisiert gespeichert wird. Das wäre eine ziemlich
blödsinnige Architektur, aber mir fällt momentan kein Grund ein,
warum das nicht standardkonform sein sollte.
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Stefan Reuther
2016-10-15 20:16:01 UTC
Permalink
Post by Peter J. Holzer
Post by Stefan Reuther
Post by Peter J. Holzer
Darüber, ob "differ in signedness" die bestmögliche Formulierung ist,
kann man streiten, aber ich halte es nicht für falsch: Die "signedness"
von "signed char" ist "signed", die von "unsigned char" ist "unsigned"
und die von "char" ist "implementation-defined". Das sind 3
verschiedene "signedness"es.
Fast. Der Denkfehler, dem Helmut unterliegt (und den deine Formulierung
nicht ausräumt) ist, dass 'char' je nach Implementation entweder der
gleiche Typ wie 'signed char' oder 'unsigned char' ist.
Es ist immer gefährlich, darüber zu spekulieren, was jemand denkt oder
nicht denkt. Da Helmut mehrmals geschrieben hat, dass er sich dessen
bewusst ist, dass es verschiedene Typen sind, glaube ich aber, dass Du
unrecht hast. Er glaubt nicht, dass es der gleiche Typ ist, aber er ist
der Meinung, dass »char« die gleiche »signedness« hat wie »unsigned
char« und daher die Warnung falsch ist.
Und für die konkrete Implementation, die er verwendet (gcc
-funsigned-char) hat er recht: Sowohl char als auch unsigned char sind
unsigned.
Sie sind aber halt verschiedene Typen.

Es klang hier an einigen Stellen so, als würde erwartet, dass
'-funsigned-char' dafür sorgt, dass 'char' und 'unsigned char' der
gleiche Typ sind. Das ist eben nicht so.
Post by Peter J. Holzer
Aber das ist eben nicht das, wovor der Compiler hier warnen will: Er
sagt nicht, "Vorsicht, ich erzeuge jetzt gerade Code, der vielleicht
nicht tut, was Du willst", sondern "Vorsicht, der Source-Code den Du
geschrieben hast, wird auf vielen Implementationen vielleicht nicht das
tun, was Du willst".
[...]
Post by Peter J. Holzer
Post by Stefan Reuther
Insofern warnt der Compiler hier nicht vor einem Portabilitätsproblem,
sondern vor einem realen Typproblem.
Ich sehe hier den Widerspruch nicht. Es ist ein reales Typproblem, ja.
aber es ist deshalb real, weil es ein Portabilitätsproblem ist. Auf der
Architektur, für die der Compiler gerade übersetzt, existiert das
Problem nicht, aber es existiert auf anderen.
Das wird vielleicht philosophisch, aber eine Warnung "der Sprachstandard
lässt das, was du da zu tun versuchst, eigentlich nicht zu, aber ich
drück mal ein Auge zu" nicht als Portabilitätswarnung einstufen.

Mal überspitzt: ich habe C als Hochsprache gewählt, weil ich dessen
Typsystem haben möchte, das eben zwischen 'char' / 'unsigned char' /
'signed char' unterscheidet. Sonst hätte ich eine Sprache genommen, die
nur den Datentyp 'byte' hat.

'struct a { int x, y; }' und 'struct b { int i, j; }' haben auch die
selbe Repräsentation, immer, mit jedem Compiler; dennoch wird die
Zuweisung eines 'struct a*' an einen 'struct b*' vom Typsystem nicht
gestattet.


Stefan
Helmut Schellong
2016-10-15 13:45:34 UTC
Permalink
[...]
Post by Stefan Reuther
Post by Peter J. Holzer
Das sind 3
verschiedene "signedness"es.
Fast. Der Denkfehler, dem Helmut unterliegt (und den deine Formulierung
nicht ausräumt) ist, dass 'char' je nach Implementation entweder der
gleiche Typ wie 'signed char' oder 'unsigned char' ist. Aber das ist
nicht so, auch mit '-funsigned-char' ist 'char' ein von 'unsigned char'
verschiedener Typ, sie haben nur den gleichen Wertebereich und die
gleiche Repräsentation. Genauso wie 'int' und 'long' auf i386 gleichen
Wertebereich und Repräsentation haben, aber verschiedene Typen sind.
Insofern warnt der Compiler hier nicht vor einem Portabilitätsproblem,
sondern vor einem realen Typproblem.
Am 10.10. 17:23
=======================================================================
Die drei char-Typen sind unterschiedliche Typen, laut Standard. Ja.

Es wird /heute/ also den unterschiedlichen Bezeichnern (dem literalen
Unterschied) 'char' und 'unsigned char' Vorrang eingeräumt gegenüber
der konkret vorliegenden Realität:
char: 0..255
unsigned char: 0..255
wird ignoriert.
Warnungen über unterschiedliche Signedness sind hier eine Falschaussage!
Weil _beide_ Typen tatsächlich kein Vorzeichen haben.
========================================================================
schrieb ich im Start-Posting - frühzeitiger geht's nicht.
Also kein Denkfehler.

Interessant ist, daß gcc winzige Unterschiede in den .s-Dateien macht.
Trotz gleichem Wertebereich und Bit-Repräsentation:

-rw-r--r-- 1 root wheel 1168580 Oct 15 15:18 bsh_c.s
-rw-r--r-- 1 root wheel 1168642 Oct 15 15:19 bsh_uc.s

Ich schätze aus Erfahrung, daß icc hier keinen Unterschied machte.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-15 14:28:59 UTC
Permalink
Post by Helmut Schellong
Interessant ist, daß gcc winzige Unterschiede in den .s-Dateien macht.
-rw-r--r-- 1 root wheel 1168580 Oct 15 15:18 bsh_c.s
-rw-r--r-- 1 root wheel 1168642 Oct 15 15:19 bsh_uc.s
^^^^
Du komplierst als Root? *grusel*

Was hast du genau zwischen den Dateien geändert? Und was ist in dem
Zusammenhang "winzig", hast du dir angeschaut, ob da anderer Code
rauskomt?

Interessanter wäre die Ausgabe von "diff *.s | wc -l", wobei man dabei
natürlich irgendwelche beliebigen Registerumbenennungen mitnimmt.
Post by Helmut Schellong
Ich schätze aus Erfahrung, daß icc hier keinen Unterschied machte.
Solche Schätzungen können bekanntlich monumental daneben liegen.
Helmut Schellong
2016-10-15 15:01:49 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Interessant ist, daß gcc winzige Unterschiede in den .s-Dateien macht.
-rw-r--r-- 1 root wheel 1168580 Oct 15 15:18 bsh_c.s
-rw-r--r-- 1 root wheel 1168642 Oct 15 15:19 bsh_uc.s
^^^^
Du komplierst als Root? *grusel*
Ich arbeite seit 1987 als root, und immer nur als root.
Post by Thomas Koenig
Was hast du genau zwischen den Dateien geändert? Und was ist in dem
Zusammenhang "winzig", hast du dir angeschaut, ob da anderer Code
rauskomt?
Ich habe gar nichts zwischen den Dateien geändert. Der gcc tat das.
Was ist winzig?
Der Größenunterschied 1.000053055845556145 ist m.E. winzig.
Die Exe haben ebenfalls einen winzigen Unterschied.
Post by Thomas Koenig
Interessanter wäre die Ausgabe von "diff *.s | wc -l", wobei man dabei
natürlich irgendwelche beliebigen Registerumbenennungen mitnimmt.
diff benutzte ich schon zuvor, bringt aber nicht viel, weil die
Differenzen 550000 Byte betragen, 47000 Zeilen.
Aber, es sind fast nur unterschiedliche Sprunglabel .L23745, etc.

Es sollten hier keine Unterschiede resultieren.
Das ist etwas suspekt!
Post by Thomas Koenig
Post by Helmut Schellong
Ich schätze aus Erfahrung, daß icc hier keinen Unterschied machte.
Solche Schätzungen können bekanntlich monumental daneben liegen.
Ich hatte schon einen Fall, wo alle Compiler unterschiedliche
Unterschiede machten - nur icc nicht.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Juergen Ilse
2016-10-15 19:21:10 UTC
Permalink
Hallo,
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Interessant ist, daß gcc winzige Unterschiede in den .s-Dateien macht.
-rw-r--r-- 1 root wheel 1168580 Oct 15 15:18 bsh_c.s
-rw-r--r-- 1 root wheel 1168642 Oct 15 15:19 bsh_uc.s
Du komplierst als Root? *grusel*
Ich arbeite seit 1987 als root, und immer nur als root.
Warum sabotierst du aktiv die Rechtetrennung als Security-Komponente des
Betriebssystems?

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Helmut Schellong
2016-10-15 20:39:42 UTC
Permalink
Post by Juergen Ilse
Post by Helmut Schellong
Post by Thomas Koenig
Du komplierst als Root? *grusel*
Ich arbeite seit 1987 als root, und immer nur als root.
Warum sabotierst du aktiv die Rechtetrennung als Security-Komponente des
Betriebssystems?
An dem System arbeite /nur/ ich, seit 1987.
Es ist mein Privat-Computer.
Es wäre 'Angeberei', ein User-Management zu betreiben.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
David Seppi
2016-10-16 00:00:42 UTC
Permalink
Post by Helmut Schellong
An dem System arbeite /nur/ ich, seit 1987.
Es ist mein Privat-Computer.
Es wäre 'Angeberei', ein User-Management zu betreiben.
Hängt Dein Computer im Internet?
--
David Seppi
1220 Wien
Helmut Schellong
2016-10-16 10:04:53 UTC
Permalink
Post by David Seppi
Post by Helmut Schellong
An dem System arbeite /nur/ ich, seit 1987.
Es ist mein Privat-Computer.
Es wäre 'Angeberei', ein User-Management zu betreiben.
Hängt Dein Computer im Internet?
Ja, per Seamonkey.
Aber der Router läßt keine Anfragen von außen durch.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-16 10:23:52 UTC
Permalink
Post by Helmut Schellong
Post by David Seppi
Post by Helmut Schellong
An dem System arbeite /nur/ ich, seit 1987.
Es ist mein Privat-Computer.
Es wäre 'Angeberei', ein User-Management zu betreiben.
Hängt Dein Computer im Internet?
Ja, per Seamonkey.
Aber der Router läßt keine Anfragen von außen durch.
Und im Gegensatz zu allen anderen hat Seamonkey bei keine
Schwachstellen, die bei Besuch von Webseiten ausgenutzt werden
können?
Helmut Schellong
2016-10-16 10:28:47 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Post by David Seppi
Post by Helmut Schellong
An dem System arbeite /nur/ ich, seit 1987.
Es ist mein Privat-Computer.
Es wäre 'Angeberei', ein User-Management zu betreiben.
Hängt Dein Computer im Internet?
Ja, per Seamonkey.
Aber der Router läßt keine Anfragen von außen durch.
Und im Gegensatz zu allen anderen hat Seamonkey bei keine
Schwachstellen, die bei Besuch von Webseiten ausgenutzt werden
können?
Unter FreeBSD - nein, keine.
Ich arbeite jetzt seit 1987 grundsätzlich ohne Sicherheitssoftware
wie Virenscanner, ohne je einen Schaden gehabt zu haben.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-10-16 10:41:27 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Post by David Seppi
Post by Helmut Schellong
An dem System arbeite /nur/ ich, seit 1987.
Es ist mein Privat-Computer.
Es wäre 'Angeberei', ein User-Management zu betreiben.
Hängt Dein Computer im Internet?
Ja, per Seamonkey.
Aber der Router läßt keine Anfragen von außen durch.
Und im Gegensatz zu allen anderen hat Seamonkey bei keine
Schwachstellen, die bei Besuch von Webseiten ausgenutzt werden
können?
Unter FreeBSD - nein, keine.
*prust*

Schon mal unter

https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Seamonkey

nachgeschaut?

Hinweis: Es gibt 704 Einträge in der Liste.
Helmut Schellong
2016-10-15 17:51:34 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Interessant ist, daß gcc winzige Unterschiede in den .s-Dateien macht.
-rw-r--r-- 1 root wheel 1168580 Oct 15 15:18 bsh_c.s
-rw-r--r-- 1 root wheel 1168642 Oct 15 15:19 bsh_uc.s
Was hast du genau zwischen den Dateien geändert?
Meinst Du die Quelle?
In der habe ich das geändert, was hier im Thread Kontext ist:
#define byte char //bsh_c.s
#define byte unsigned char //bsh_uc.s
Natürlich beides mit -funsigned-char.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-10-15 20:17:49 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Interessant ist, daß gcc winzige Unterschiede in den .s-Dateien macht.
-rw-r--r-- 1 root wheel 1168580 Oct 15 15:18 bsh_c.s
-rw-r--r-- 1 root wheel 1168642 Oct 15 15:19 bsh_uc.s
^^^^
Du komplierst als Root? *grusel*
DOS-Benutzer halt, die kennen nix andres :-)
Post by Thomas Koenig
Interessanter wäre die Ausgabe von "diff *.s | wc -l", wobei man dabei
natürlich irgendwelche beliebigen Registerumbenennungen mitnimmt.
Einen Unterschied von 62 Bytes kann man fast schon mit den
Debuginformationen für den längeren Dateinamen erklären.


Stefan
Helmut Schellong
2016-10-15 20:44:37 UTC
Permalink
Post by Stefan Reuther
Post by Thomas Koenig
Du komplierst als Root? *grusel*
DOS-Benutzer halt, die kennen nix andres :-)
Ich gehöre zu den wenigen, die mit Unix begonnen haben, und
erst danach DOS und Windows kennenlernten.
Post by Stefan Reuther
Einen Unterschied von 62 Bytes kann man fast schon mit den
Debuginformationen für den längeren Dateinamen erklären.
==========================================================
16934c16934
< je .L3045
---
Post by Stefan Reuther
je .L3046
16938c16938
< je .L3046
---
Post by Stefan Reuther
je .L3047
16981c16981
< .L3045:
---
16990c16990
< .L3046:
---
17007c17007
< je .L2947
---
Post by Stefan Reuther
je .L3029
17009,17011c17009,17012
< jg .L3047
< movsx rbx, DWORD PTR [rax+12]
< add rbx, QWORD PTR [rax]
---
Post by Stefan Reuther
jg .L3048
movsx rdx, DWORD PTR [rax+12]
add rdx, QWORD PTR [rax]
mov rax, rdx
17013c17014
< mov QWORD PTR CstrP[rip], rbx
---
Post by Stefan Reuther
mov QWORD PTR CstrP[rip], rax
17029c17030
< .L3047:
---
17033a17035,17038
Post by Stefan Reuther
mov rax, rbx
jmp .L2947
mov rax, rbx
17036c17041
< .L3056:
---
17062c17067
< .L3057:
---
17080c17085
< je .L3048
---
Post by Stefan Reuther
je .L3049
17089c17094
< je .L3036
---
Post by Stefan Reuther
je .L3037
17091c17096
< je .L3036
---
Post by Stefan Reuther
je .L3037
17102c17107
< je .L3049
---
Post by Stefan Reuther
je .L3050
...
==========================================================
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-10-12 15:20:49 UTC
Permalink
Post by Peter J. Holzer
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Heute jedoch erhält man dabei z.B. 1000 Warnmeldungen.
Hauptsächlich wegen (angeblich) unterschiedlicher Vorzeichenbehaftung.
Hast du auch einen Testfall, der das demonstriert? So allgemein kann
man mit der Aussage erst mal nix anfangen.
http://www.schellong.de/txt/gccw
Da stehen ein Haufen Fehlermeldungen, aber nicht genügend Informationen,
weil ein Beispiel-Quelltext fehlt.
Was willst Du denn da heraus lesen?
Der gcc zeigt doch den Quelltext zu jedem Fehler.
Mit einer Zeile Quelltext (ohne Kontext, wie z.B. die dazugehörigen
Deklarationen) kann man wenig anfangen.
Schreib ein vollständiges Programm, das den Fehler demonstriert, dann
kann man darüber diskutieren. So ist das vollkommen sinnlos.
#include <stdio.h>

int main(void)
{
unsigned char *s = "Ali Baba und die 40 Compiler";

puts(s);
return 0;
}

---------------

[***@doppelsaurus]/tmp#gcc -funsigned-char -W -Wall a.c
#a.c: In function 'main':
a.c:5:24: warning: pointer targets in initialization differ in signedness [-Wpointer-sign]
a.c:7:5: warning: pointer targets in passing argument 1 of 'puts' differ in signedness [-Wpointer-sign]
In file included from a.c:1:0:
/usr/include/stdio.h:688:12: note: expected 'const char *' but argument is of type 'unsigned char *'

Allerdings behandle ich das lediglich als [fuer mich] nutzlose Warnung,
dh, ich ignoriere sie oder stelle sie ab.
Loading...