Wird wohl verschwinden, wenn man striktes Aliasing abschaltet.
Ansonsten: https://en.wikipedia.org/wiki/Pointer_aliasing
Man sollte sich dabei natürlich nicht bloss die Warnung abschalten (das
ginge u.U. auch direkt), sondern sicher sein, dass durch das gewarnte
Aliasing kein Problem dräut.
Ein Problem, das Du Dir da einhandelst, kann der nichtalignte
32-Bit-Zugriff sein. Es gibt Prozessorarchitekturen, bei denen das
einfach nur etwas langsamer wird (x86), aber es gibt auch
Prozessorarchitekturen, bei denen so etwas gar nicht erst vorgesehen
ist.
Wenn Deine Arrays nicht auf einer auf 32-Bit-Zugriffe ausgerichteten
Adresse anfangen, tritt dieses Problem auf.
Es ist natürlich bequem, durch diese Typecast-Konstruktion einen
32-Bit-Wert aus einem 4-Byte-Array zu generieren, aber "sauber" ist das
nicht. Insbesondere, weil es sich nicht um die Byte-Order (little oder
big-Endian) kümmert.
Normalerweise bieten Compiler für so lustige Casts Macros an, die meist
irgendwie mit "SIMD" benannt werden. SIMD steht in diesem Fall für
"Single Instruction Multiple Data", da solche "Späße" bei DSP
Anwendungen recht häufig vorkommen. Sprich auf irgendwelchen Werten, die
eigentlich keine 32bit haben, werden Rechenoperationen für 32bit
angewandt...
Im Fall von ARM und GCC wäre das Macro etwa
__SIMD32(x)
Den Datentyp von dest_ip hast du uns noch verheimlicht?
Is der unsigned long?
Für Leute, die Macros ungern nutzen (wenn auch Compiler interne...)
würden sich hier Unions anbieten.
Warum ist myip und ein Byte-Array, dest_ip aber ein 32-Bit-Integer? Das
sind doch beides IP-Adressen, wäre es deswegen nicht sinnvoll, für
beiden den gleichen Datentyp zu verwenden?
Ich würde beide vom Typ unsigned long, oder noch besser uint32_t machen,
ebenso netmask. Dann kannst du die Adressen nach Belieben maskieren (&),
vergleichen (==) und zuweisen (=), ohne dafür eine Cast-Orgie
veranstalten zu müssen. Du brauchst dann auch kein memcpy oder memcmp.
Das macht das Programm ganz nebenbei um ein Vielfaches übersichtlicher.
Wenn du woanders im Programm tatsächlich auf die einzelnen Bytes der
Adresse zugreifen möchtest, um sie von der oder in die human-readable
Darstellung zu konvertieren, kannst du das dort über einen Cast in einen
unsigned-char- bzw. uint8_t-Pointer machen. In diese Richtung ist der
Cast nämlich erlaubt und führt zu keiner Warnung. Alternativ kannst du
dafür auch eine Union verwenden.
Rufus Τ. F. schrieb:> Wenn Deine Arrays nicht auf einer auf 32-Bit-Zugriffe ausgerichteten> Adresse anfangen, tritt dieses Problem auf.
die Pointer-Aliasing Problematik hat nichts (oder höchstens am Rande)
mit unaligned-Zugriffen zu tun.
Die Problematik ist (in diesem konkreten Beispiel nicht unbedingt
offensichtlich), daß sich Zeiger überlappen können.
Das verhindert bessere Optimierungen, weil der Compiler dereferenzierte
Werte nicht in Registern halten, sondern immer aufs Neue lesen muß.
Leider sind nicht alle gcc Versionen mit einer gleich guten Erkennung
gesegnet, wann das tatsächlich ein Problem sein könnte und wann nicht.
-fno-strict-aliasing als Antwort auf die Warnung ist nicht unbedingt
eine gute Lösung. gcc wird sich mit schlechter Registernutzung bedanken
und paranoid alle Zeiger unnötig oft dereferenzieren.
Wenn man sicher ist, daß Überlappungen ausgeschlossen sind, kann man die
Zeiger als _restrict_ (oder nur restrict bei C99) deklarieren und
erklärt gcc, daß der dahinterliegende Speicher ausschließlich über
diesen Zeiger angefaßt wird.
Ähnlich wie const ist das eine Zusicherung an den Compiler. Bricht man
sie, kracht's u.U.
A. K. schrieb:> Wird wohl verschwinden, wenn man striktes Aliasing abschaltet.
Aliasing wird bei mir grundsätzlich abgeschaltet.
Das Risiko, ein Aliasing zu übersehen (insbesondere bei Code für
performante De/Serialisierung) ist hoch. Und GCC warnt quasi nur bei den
(offensichtlichen) Fällen, wo es keine Probleme gibt. Die wirklichen
Probleme sieht er aber nicht, wie auch.
Mein Empfehlung: Bei Optimierungen (-O2 und mehr) immer
-fno-strict-aliasing hinzufügen, es sei denn man weiß wirklich was man
da tut.
Hier noch ein alter (veralteter?) Link, der recht witzig ist. Linus
halt. ;-)
http://lkml.org/lkml/2003/2/26/158
Markus F. schrieb:> die Pointer-Aliasing Problematik hat nichts (oder höchstens am Rande)> mit unaligned-Zugriffen zu tun.
Das wollte ich damit auch nicht zum Ausdruck bringen, das ist ein
zusätzliches Problem. Wenn auch nicht im konkreten Fall, dem 8-Bit-AVR
ist Alignment herzlich Wurscht.
Mikro 7. schrieb:> Aliasing wird bei mir grundsätzlich abgeschaltet.
Was machst du, wenn dein Code irgendwann einmal mit einem anderen
Compiler übersetzt werden soll, der diese Abschaltmöglichkeit nicht
bitetet?
> Und GCC warnt quasi nur bei den (offensichtlichen) Fällen, wo es keine> Probleme gibt. Die wirklichen Probleme sieht er aber nicht, wie auch.
Bist du sicher?
Ich würde sagen, er warnt viel zu oft, um sicher zu sein, auch die
tatsächlich relevanten, aber schwer erkennbaren Fälle abzudecken.
Oder hast du ein Beispiel für einen Fehler, der mit -fno-strict-aliasing
vermieden worden wäre und wo der GCC trotzdem nicht gewarnt hat?
Yalu X. schrieb:> Was machst du, wenn dein Code irgendwann einmal mit einem anderen> Compiler übersetzt werden soll, der diese Abschaltmöglichkeit nicht> bitetet?
Hoffen. Wie jeder andere auch. ;-)
> Ich würde sagen, er warnt viel zu oft, um sicher zu sein, auch die> tatsächlich relevanten, aber schwer erkennbaren Fälle abzudecken.
Er probiert es.
Durch die vielen False Positives sind die Warnings aber praktisch kaum
brauchbar. -.-
> Oder hast du ein Beispiel für einen Fehler, der mit -fno-strict-aliasing> vermieden worden wäre und wo der GCC trotzdem nicht gewarnt hat?
GCC says so:
-Wstrict-aliasing
This option is only active when -fstrict-aliasing is active. It
warns about code which might break the strict aliasing rules that the
compiler is using for optimization. The warning does not catch all
cases, but does attempt to catch the more common pitfalls. It is
included in -Wall. It is equivalent to -Wstrict-aliasing=3
Markus F. schrieb:> -fno-strict-aliasing als Antwort auf die Warnung ist nicht unbedingt> eine gute Lösung. gcc wird sich mit schlechter Registernutzung bedanken> und paranoid alle Zeiger unnötig oft dereferenzieren.
Ich habe das mal mit GCC bei einem ziemlich Pointer-intensiven Programm
nachgemessen.
Ergebnis: strict-aliasing brachte zwar dieselben Ergebnisse wie
no-strict-aliasing (schonmal gut), aber keinerlei meßbaren
Performancegewinn. Also lieber abschalten.
Je nach Anwendung mag das natürlich anders ausfallen, aber man sollte
das schon konkret mal nachmessen, ob es den potentiellen Ärger überhaupt
wert ist.