glibc: abs() hat int als Rückgabetyp. Warum?

Gast #6311750
Lesenswert?

Hallo,

warum hat die Funktion abs() "int" als Rückgabetyp?

https://github.com/bminor/glibc/blob/master/stdlib/abs.c

http://git.musl-libc.org/cgit/musl/tree/src/stdlib/abs.c

Das würde doch bei INT_MIN einen falschen Wert liefern. Weil INT_MAX ja 
um 1 kleiner als |INT_MIN| (Betrag) ist.

Ein "unsigned int"-Wert wäre doch sinnvoller oder nicht?
Gast #6311755
Lesenswert?

Nicht unbedingt: in den meisten realen Anwendungen willst du das 
Ergebnis ja weiterverarbeiten. Addieren, multiplizieren, vergleichen. 
Und da nützt dir ein unsigned dazwischen meist nichts.
Gast #6311876
Lesenswert?

zitter_ned_aso schrieb:
> Das würde doch bei INT_MIN einen falschen Wert liefern. Weil INT_MAX ja
> um 1 kleiner als |INT_MIN| (Betrag) ist.

Zumindest beim Zweierkomplement. Daher ist auf solchen Systemen 
abs(INT_MIN) nicht definiert. Bei Systemen mit Einerkomplement ist es 
kein Problem, da dort abs(INT_MAX) == abs(INT_MIN) == INT_MAX ist.

> Ein "unsigned int"-Wert wäre doch sinnvoller oder nicht?

Das ist so eine Sache. abs() ist schon ziemlich lange in C. Meines 
Wissens war es schon in der ersten Version des ANSI-C Standards im Jahr 
1989. Schon damals war bekannt dass abs(INT_MIN) ein Problem sein kann. 
Das Verhalten nach 30 Jahren zu ändern? Wer weiß wie viel vorhandener 
Code dann auseinander fliegt.
Gast #6311901
Lesenswert?

Michael Gugelhupf schrieb:
> Daher ist auf solchen Systemen abs(INT_MIN) nicht definiert.

Damit kann man übrigens schöne vulnerabilities bauen. Haben wir im 
Studium als Übungsaufgabe bekommen (vuln finden und exploiten).

> Das Verhalten nach 30 Jahren zu ändern? Wer weiß wie viel vorhandener
> Code dann auseinander fliegt.

Korrekt. Eigentlich muss man vor jeder Verwendung einer 
Standard-C-Funktion die zugehörige manpage lesen und sich solcher und 
ähnlicher Fallstricke bewusst sein.

man 3 abs:
> NOTES
>        Trying to take the absolute value of the most negative
>        integer is not defined.
#6312058
Lesenswert?

Bastler schrieb:
> zitter_ned_aso schrieb:
>> warum hat die Funktion abs() "int" als Rückgabetyp?
>
> Weil in den meisten Programmiersprachen, C eingeschlossen, der Datentyp
> nichts mit dem Zahlenart im mathematischen Sinne zu tun hat.

Aber eigentlich wählt man den Datentyp geschickterweise so, dass er den 
nötigen Wertebereich auch voll unterstützt. Das ist hier nicht gegeben, 
da abs(INT_MAX) eben beim Zweierkomplement auf Grund des Rückgabetyps 
nicht darstellbar ist.

Jens schrieb:
> Eigentlich muss man vor jeder Verwendung einer Standard-C-Funktion die
> zugehörige manpage lesen und sich solcher und ähnlicher Fallstricke bewusst
> sein.

Nicht unbedingt vor jeder Verwendung, denn diese Fallstricke ändern sich 
ja nicht dauernd. Aber man sollte für jede Funktion wissen, welche 
potenziellen Probleme es damit geben kann und diese entsprechend 
berücksichtigen.
Wenn man eine Funktion nur alle 5 Jahre mal benutzt, ist es aber 
natürlich besser, jedes mal nachzuschauen.
Moderator #6312061
Lesenswert?

zitter_ned_aso schrieb:
> warum hat die Funktion abs() "int" als Rückgabetyp?

> Ein "unsigned int"-Wert wäre doch sinnvoller oder nicht?

Aus dem gleiche Grund könntest du fragen, warum die Addition und
Multiplikation zweier int-Werte wieder ein int und nicht ein long
ergeben.

In C sind alle arithmetischen Datentypen mit einer Größe von mindestens
int bzgl. aller darauf definierter Rechenoperationen abgeschlossen (bzw.
für bestimmte Operanden undefiniert). Da wäre es komisch, wenn abs eine
Ausnahme machen würde.
#6312085
Lesenswert?

Yalu X. schrieb:
> Aus dem gleiche Grund könntest du fragen, warum die Addition und
> Multiplikation zweier int-Werte wieder ein int und nicht ein long
> ergeben.

Gerade bei der Multiplikation wäre das durchaus sehr praktisch gewesen. 
Auf Assembler-Ebene passiert meistens genau das: Das Ergebnis ist 
doppelt so breit wie die Operanden. Aber da C das nicht auch so macht, 
muss man Multiplikation dort öfter mal mit dem doppelten der eigentlich 
benötigten Bitbreite durchführen, damit nicht die Hälfte des Ergebnisses 
verworfen wird.
1
void func(int16_t a, int16_t b)
2
{
3
    // Rechnung als 16 Bit * 16 Bit, Ergebnis wird abgeschnitten
4
    int32_t result = a * b;
5

6
     // korrektes Ergebnis, aber Multiplikation muss (meist unnötigerweise) in
7
     // 32 Bit durchgeführt werden.
8
     int32_t result = (int32_t)a * (int32_t)b;
9
}
Gast #6312153
Lesenswert?

Rolf M. schrieb:
> Aber da C das nicht auch so macht,
> muss man Multiplikation dort öfter mal mit dem doppelten der eigentlich
> benötigten Bitbreite durchführen, damit nicht die Hälfte des Ergebnisses
> verworfen wird.

Dass ist dann der Moment wo du hoffst, dass der Optimizer erkennt was 
wirklich passieren soll und selbstständig eine 16x16 -> 32 Bit 
Multiplikation einfügt.
#6312255
Lesenswert?

Michael Gugelhupf schrieb:
> dass der Optimizer erkennt was
> wirklich passieren soll und selbstständig eine 16x16 -> 32 Bit
> Multiplikation einfügt.

Das hat überhaupt nichts mit dem Optimizer zu tun und irgendeiner 
magischen Erweiterung von 16 auf 32 Bit.
Die Prozesse, die im Compiler ablaufen, heißen Typ-Promotion und 
Typ-Balancierung. Diese sind sehr genau definiert und keineswegs 
zufällig von irgendeiner Implementierung des Optimizers abhängig.
Gast #6312367
Lesenswert?

MaWi N. schrieb:
> Das hat überhaupt nichts mit dem Optimizer zu tun und irgendeiner
> magischen Erweiterung von 16 auf 32 Bit.
> Die Prozesse, die im Compiler ablaufen, heißen Typ-Promotion und
> Typ-Balancierung. Diese sind sehr genau definiert und keineswegs
> zufällig von irgendeiner Implementierung des Optimizers abhängig.

Das ist jetzt auch wieder so eine Antwort die du nur geschrieben hast um 
irgend was zu sagen?

Im C Standard ist klar geregelt das der Compiler optimieren darf wenn 
das Ergebnis genau so aussieht wie wenn er die vorgegebenen Abläufe 
wörtlich ausführen würde.
#6312377
Lesenswert?

MaWi N. schrieb:
> Michael Gugelhupf schrieb:
>> dass der Optimizer erkennt was
>> wirklich passieren soll und selbstständig eine 16x16 -> 32 Bit
>> Multiplikation einfügt.
>
> Das hat überhaupt nichts mit dem Optimizer zu tun und irgendeiner
> magischen Erweiterung von 16 auf 32 Bit.

Doch, hat es. Du hast das Problem nur noch nicht verstanden.

> Die Prozesse, die im Compiler ablaufen, heißen Typ-Promotion und
> Typ-Balancierung. Diese sind sehr genau definiert und keineswegs
> zufällig von irgendeiner Implementierung des Optimizers abhängig.

Das hat auch keiner behauptet. Wenn ich aber einen 16 Bit breiten int 
habe und den mit einem zweiten int multipliziere, wird eine 
16-Bit-Multiplikation durchgeführt und damit ist das Ergebnis aber auch 
auf 16 Bit begrenzt, selbst wenn der Prozessor eine Instruktion hat, die 
daraus ein 32-Bit-Ergebnis produziert. Dann wirft der Compiler einfach 
die obere Hälfte des Ergebnisses weg.
Will ich ein 32-Bit-Ergebnis, muss ich mindestens einen der Operanden 
auf 32 Bit casten, obwohl ich nur eine 16x16-Bit-Multikplikation 
brauche. Und dann muss ich hoffen, dass der Compiler merkt, dass der 
Operand eigentlich ein 16-Bit-Wert wäre und nur auf 32 Bit gecastet 
wird, damit ich auch ein 32-bit-Ergebnis bekomme.
Gast #6312399
Lesenswert?

Rolf M. schrieb:
> Aber eigentlich wählt man den Datentyp geschickterweise so, dass er den
> nötigen Wertebereich auch voll unterstützt.

Ein frommer Wunsch, der eine Sprache wie C zur praktischen 
Nicht-Nutzbarkeit degradieren würde.

Selbst bei einer einfachen Addition müsste der Ergebnis-Datentyp um 
mindestens 1-Bit größer sein, als der größte der beiden Operanden.

Der Denkfehler ist, ein C-Datentyp wie "int" wäre identisch zum 
Zahlenbereich der ganzen Zahlen mit ihren Gesetzen.
Gast #6312412
Lesenswert?

Rolf M. schrieb:
> Und dann muss ich hoffen, dass der Compiler merkt, dass der
> Operand eigentlich ein 16-Bit-Wert wäre und nur auf 32 Bit gecastet
> wird, damit ich auch ein 32-bit-Ergebnis bekomme.

Die Vorstellung, die Definition einer Programmiersprache wie C hat etwas 
mit einer konkreten Implementierung für einen spezifischen Prozessor zu 
tun, ist infantil.

Und ja, wenn Du in der Sprache C ein 32-Bit Ergebnis einer 
16x16-Multiplikation haben willst, musst Du vorher casten. Genau so 
funktioniert es eben in "C". Wie das der Compiler in Maschinensprache 
umsetzt, ist in C eben nicht definiert.
Beitrag #6312428 wurde von einem Moderator gelöscht.
#6312478
Lesenswert?

Bastler schrieb:
> Rolf M. schrieb:
>> Und dann muss ich hoffen, dass der Compiler merkt, dass der
>> Operand eigentlich ein 16-Bit-Wert wäre und nur auf 32 Bit gecastet
>> wird, damit ich auch ein 32-bit-Ergebnis bekomme.
>
> Die Vorstellung, die Definition einer Programmiersprache wie C hat etwas
> mit einer konkreten Implementierung für einen spezifischen Prozessor zu
> tun, ist infantil.

Allerdings ist es genauso "infantil" zu glauben, dass 
Programmiersprachen, zumindest solche eher hardwarenahen wie C, völlig 
losgelöst von jeglichen Hardware-Eigenschaften der üblichen 
Architekturen entwickelt werden. Denn am Ende soll die Sache ja auch 
performant sein.

> Und ja, wenn Du in der Sprache C ein 32-Bit Ergebnis einer
> 16x16-Multiplikation haben willst, musst Du vorher casten. Genau so
> funktioniert es eben in "C".

Ist das deiner Erfahrung nach auch die Art, wie es die überwiegende Zahl 
der CPU-Architekturen umsetzt? Die, die ich kenne, machen es alle nicht 
so.

> Wie das der Compiler in Maschinensprache umsetzt, ist in C eben nicht
> definiert.
#6312536
Lesenswert?

Rolf M. schrieb:
> Wenn ich aber einen 16 Bit breiten int
> habe und den mit einem zweiten int multipliziere, wird eine
> 16-Bit-Multiplikation durchgeführt und damit ist das Ergebnis aber auch
> auf 16 Bit begrenzt, selbst wenn der Prozessor eine Instruktion hat, die
> daraus ein 32-Bit-Ergebnis produziert. Dann wirft der Compiler einfach
> die obere Hälfte des Ergebnisses weg.

Falsch.
1
$ cat t.c 
2
#include <stdio.h>
3
#include <stdint.h>
4
int main(void)
5
{
6
        int16_t a = 30000;
7
        int16_t b = 30000;
8
        int32_t c = a * b;
9
        printf("%d\n", c);
10
}
11
$ gcc -o t t.c
12
$ ./t
13
900000000
#6312573
Lesenswert?

Yalu X. schrieb:
> @MaWi: Ihr redet aneinander vorbei.
>
> Rolf schrieb von einem 16 Bit breiten int, du hingegen verwendest auf
> einem System mit 32 Bit breitem int ein int16_t. Auf diesem System ist
> int16_t eben etwas anderes als int.

Ja genau. Hiermit:

Rolf M. schrieb:
> Wenn ich aber einen 16 Bit breiten int habe und den mit einem zweiten int
> multipliziere, wird eine 16-Bit-Multiplikation durchgeführt

meinte ich nicht den Fall irgendeines 16 Bit breiten Integer-Typen, 
sondern wirklich speziell den Fall, dass ich einen Compiler habe, bei 
dem der Datentyp "int" 16 Bit breit ist. War vielleicht etwas 
missverständlich formuliert.
Gast #6312897
Lesenswert?

Rolf M. schrieb:

> meinte ich nicht den Fall irgendeines 16 Bit breiten Integer-Typen,
> sondern wirklich speziell den Fall, dass ich einen Compiler habe, bei
> dem der Datentyp "int" 16 Bit breit ist.

Das ist in der Realität nur auf zwei Sorten von CPUs der Fall:

1) 8-Bitter, weil int mindestens 16 bit breit ist, aber da hast Du 
sowieso keine 16-bit-Multiplikation in Hardware und folglich auch kein 
32-bit-Ergebnis in Registern.

2) 16-Bitter, weil das der Registerbreite entspricht, und der letzte 
wirklich verbreitete war der 286er. Da war das tatsächlich so, daß das 
Ergebnis der Multiplikation von 16-bit-Operanden im Doppelregister DX:AX 
vorlag. Allerdings konnte man damit sowieso nicht direkt weiterrechnen, 
weil z.B. Addition nicht mit Doppelregistern ging.

Aber auch wenn man das auf einem 16-bitter mit dem manuellen 
Operanden-Cast nach int32_t macht, heißt das keineswegs, daß die 
Multiplikation selber mit 32-bit-Operanden tatsächlich so durchgeführt 
wird.

C hat nämlich die "as-if-Regel". Der Compiler darf machen, was er will, 
solange nur das Ergebnis identisch ist. Das bedeutet, daß er auf einem 
286er das hier:
1
int a = b = 300;
2
int32_t c = ((int32_t a) * ((int32_t b));

Sehr wohl optimieren darf zu genau dem, was ein 286er in Hardware kann. 
Also die Multiplikation eben nicht mit 32-bit-Operanden ausführen, 
sondern mit 16 bit, und nur das 32-bittige Ergebnis aus DX:AX in die 
Variable c schieben.

Wenn der Compiler das nicht tut, ist es ein schlechter Compiler.
Gast #6312922
Lesenswert?

hmmm, mit unsigned int kommt man also auch nicht weiter. Dann muss es so 
bleiben wie es ist ;-)

Es ist aber schon komisch, dass eine Funktion mit einem Rückgabetyp 
arbeitet, der gar nicht in der Lage ist alles darzustellen, was aus 
Funktionsparametern berechnet werden kann.

Klar, auch Rechenoperationen können zu diesem Problem führen, aber das 
sind ja keine Funktionen. Das ist für mich schon was anderes. Es gibt 
unendlich viele Zahlenn - es ist egal mit welchen Datentypen man 
rechnet. Irgendwann wird man sowieso an die Grenzen stoßen.

Eine Funktion schränkt aber durch die Parameterliste den Zahlenberech 
ein. Hier wird ja nur das Vorzeichen geändert (wenn überhaupt). Das ist 
nicht sowas wie:

pow(INT_MAX, pow(INT_MAX, INT_MAX)) usw..
Gast #6313082
Lesenswert?

> Es ist aber schon komisch, dass eine Funktion mit einem Rückgabetyp
> arbeitet, der gar nicht in der Lage ist alles darzustellen,

Ein Fall geht schief, der Rest läuft besser.

Nop hat es oben schon gesagt: unsigned ist ansteckend und versteckte 
Typenwechsel mitten in einem Ausdruck sind häßlich: "abs(3) > -1" - true 
or false?  Und "-3 * abs(3) < 0"?
#6313259
Lesenswert?

Nop schrieb:
> Rolf M. schrieb:
>
>> meinte ich nicht den Fall irgendeines 16 Bit breiten Integer-Typen,
>> sondern wirklich speziell den Fall, dass ich einen Compiler habe, bei
>> dem der Datentyp "int" 16 Bit breit ist.
>
> Das ist in der Realität nur auf zwei Sorten von CPUs der Fall:

Dann nimm halt eine Multiplikation zweier 32-bit-Integer zu einem mit 64 
Bit. Gleiches Problem, aber auch auf 32-Bit-Plattformen relevant.

> C hat nämlich die "as-if-Regel". Der Compiler darf machen, was er will,
> solange nur das Ergebnis identisch ist. Das bedeutet, daß er auf einem
> 286er das hier:
> int a = b = 300;
> int32_t c = ((int32_t a) * ((int32_t b));
> Sehr wohl optimieren darf zu genau dem, was ein 286er in Hardware kann.

Ja, natürlich. Hab ich ja auch schon geschrieben, und "Michael 
Gugelhupf" vor mir. Das hat keiner bestritten.

Yalu X. schrieb:
> zitter_ned_aso schrieb:
>> Klar, auch Rechenoperationen können zu diesem Problem führen, aber das
>> sind ja keine Funktionen.
>
> Natürlich sind das Funktionen. Sie unterscheiden sich von "gewöhnlichen"
> Funktionen nur syntaktisch:

Das stimmt nur in C++ für benutzerdefinierte Operatoren.
Gast #6313295
Lesenswert?

Rolf M. schrieb:
> Das stimmt nur in C++ für benutzerdefinierte Operatoren.

Nein, Du siehst Unterschiede wo keine sind. Ja, in C kann man Operatoren 
nicht neu definieren. Das ist aber nicht das Thema. Ein Operator ist nur 
eine Funktion in einer anderen Schreibweise.

Ob Du nun "add(a,b)" oder "a + b" schreibst, ist per se egal. Beides 
sind Funktionsaufrufe, die (mutmaßlich) zwei Parameter addieren.

Die Sprache C stellt einen festen Vorrat an Operatoren zur Verfügung, da 
kannst Du als Programmierer nix ändern. In C++ kannst Du immerhin 
existierenden Operatoren überladen. In anderen Sprachen kannst Du auch 
neue Operatoren definieren. In wiederum anderen Sprachen kannst Du jede 
Binäre Funktion in Operatorschreibweise benutzen.

Unterm Strich bleibt: Ein Operator ist nichts anderes als eine Funktion 
in anderer Schreibweise, also nur ein Unterschied im Syntax.
Gast #6313380
Lesenswert?

foobar schrieb:
> Ein Fall geht schief, der Rest läuft besser.

aber eigentlich könnte man ja sagen, dass das kein Problem von C ist. 
Die  Zweierkomplement-Darstellung hat im negativen Bereich ein Zahl 
mehr. Hätten wir hier eine Symmetrie, so gebe es dieses Problem nicht.

Oder wenn wir eine Zahl mehr im positiven Bereich hätten.
#6313640
Lesenswert?

Bastler schrieb:
> Ein Operator ist nur eine Funktion in einer anderen Schreibweise.

Nein. Für einen Operator muss ich keinen Header mit einer Deklaration 
einbinden, um ihn zu nutzen. Ich kann den selben Operator auch mit 
mehreren  verschiedenen Typen verwenden, obwohl C keine 
Funktionsüberladung kennt. Und es gibt auch nicht die gleichen 
Einschränkungen wie für den Aufruf von Funktionen, wie z.B. dass man sie 
nicht außerhalb von Funktionen aufrufen kann.
1
#include <math.h>
2

3
int x = 3 * 5;  // Erlaubt, weil das Ergebnis eine Compilezeit-Konstante ist
4
double y = sin(M_PI); // Fehler: Funktionaufrufe sind an der Stelle nicht erlaubt
5

6
int main()
7
{
8
}

Der überwiegende Teil der Operatoren stellt auch keinen Sequenzpunkt dar 
im Gegensatz zu Funktionen. Es gibt in C ziemlich viele Unterschiede 
zwischen Operatoren und Funktionen.

> In C++ kannst Du immerhin existierenden Operatoren überladen.

Ja, und das sind dann wie gesagt auch tatsächlich Funktionen, für die 
die gleichen Regeln gelten wie für andere Funktionen auch.

> In anderen Sprachen kannst Du auch neue Operatoren definieren. In wiederum
> anderen Sprachen kannst Du jede Binäre Funktion in Operatorschreibweise
> benutzen.

Mag sein, dass es Sprachen gibt, in denen es keinerlei Unterschiede 
zwischen Operatoren und Funktionen gibt. C gehört aber nicht dazu.
Moderator #6314001
Lesenswert?

Entschuldigung, ich wollte mit der Verwendung des Begriffs "Funktion"
keine Verwirrung stiften :)

Als ich oben "Funktion" schrieb, meinte ich damit keine C-Funktion,
sondern eine Funktion im mathematischen Sinn, also etwas, was einem oder
mehreren Argumenten ein Ergebnis zuordnet. Ich dachte, das würde aus dem
Kontext klar hervorgehen, hätte mich aber wohl dennoch etwas klarer
ausdrücken sollen.

In meinem ersten beitrag wollte ich dem TE klar machen, dass die von ihm
kritisierte Einengung des Wertebereichs von abs nichts Besonderes ist,
weil es diese Einengung in ähnlicher Weise auch bei Additionen und
Multiplikation gibt.

Daraufhin entgegnete er:

zitter_ned_aso schrieb:
> Klar, auch Rechenoperationen können zu diesem Problem führen, aber das
> sind ja keine Funktionen.

Er akzeptiert das Problem also bei der Addition und Multiplikation,
nicht aber bei der Absolutwertberechnung, und begründet dies damit dass
die beiden ersteren keine Funktionen seien.

Mit meiner Antwort

Yalu X. schrieb:
> Natürlich sind das Funktionen.
> ...

wollte ich deutlich machen, dass die Berechnung einer Summe oder eines
Produkts und die Berechnung des Absolutwerts nicht so unterschiedlich
sind, dass daraus die Forderung abgeleitet werden könnte, dass die
abs-Funktion für gesamten Argumentwertebereich definiert sein muss.

Addition und Multiplikation sind natürlich keine Functions im Sinne der
Sprachspezifikation von C (das können sie schon allein deswegen nicht
sein, weil ihr Name kein gültiger C-Identifier ist). Es sind aber sehr
wohl Funktionen in dem Sinne, dass sie aus einem oder mehreren (im
konkreten Fall zwei) Zahlenwerten einen Ergebniswert berechnen. Dass sie
sich von C-Funktionen in einigen Punkten (wie bspw. Sequenzpunkten)
unterscheiden, ist bei der Betrachtung der eigentlichen Berechnung und
der Wertebereiche (um die es in diesem Thread ja ausschließlich geht)
IMHO völlig irrelevant.
Moderator #6314051
Lesenswert?

zitter_ned_aso schrieb:
> abs() wäre so im mathematichen Sinne keine Funktion. Da es ja im
> Definitionsbereich eine Zahl INT_MIN gibt, zu der es keinen
> Funktionswert abs(INT_MIN) gibt.

Das ist jetzt aber ein schräger Schluss :)

Andersherum wird ein Schuh daraus:

Da der Funktionswert von INT_MIN nicht definiert ist, gehört INT_MIN
nicht zum Definitionsbereich.
Gast #6314249
Lesenswert?

zitter_ned_aso schrieb:
> abs() wäre so im mathematichen Sinne keine Funktion. Da es ja im
> Definitionsbereich eine Zahl INT_MIN gibt, zu der es keinen
> Funktionswert abs(INT_MIN) gibt.

So was nennt man glaub "partielle Funktion". Also eine Funktion die 
nicht für alle Eingangswerte ein Ergebnis liefert bzw. definiert ist. 
Eine "totale Funktion" wäre dann für alle denkbaren Eingangswerte 
definiert.
Gast #6314264
Lesenswert?

Rolf M. schrieb:
> Es gibt in C ziemlich viele Unterschiede
> zwischen Operatoren und Funktionen.

Naja, die Unterschiede sind doch aber nicht von fundamentaler Natur.

Bei einem guten Glas Wein betrachtet sind Operatoren nichts anderes als 
syntaktischer Zucker für Programmierer. Ohne Operatoren hätten wir 
vielleicht:
1
#include <stdadd.h>
2

3
int beispiel(int a, int b, int c)
4
{
5
  return addint(addint(a, b), c);
6
}

Mit Operatoren ist's halt bequemer:
1
int beispiel(int a, int b, int c)
2
{
3
  return a + b + c;
4
}

Da ist kein großer Unterschied dazwischen.
#6314270
Lesenswert?

Rolf M. schrieb:
> Auf Assembler-Ebene passiert meistens genau das: Das Ergebnis ist
> doppelt so breit wie die Operanden.

Vor Äonen war das so.

Bei einem gepipelinenten Multiplizierer  ist es jedoch sinnvoller, 
zweimal zu multiplizieren, einmal für die untere und einmal für die 
obere Hälfte, als beides zusammen zu rechnen. Grund ist das 
Ressourcenmanagement von Bussen und Registern.

Das war schon bei PowerPC so, anders als in IBMs POWER. Und die 
meistgebrauchten Multiplikationsbefehle bei x86 liefern nur die untere 
Hälfte. 32bit ARM hatte anfangs überhaupt nur diese Variante.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren