>>156631>Felix ist sich zu 99% sicher, dass genau für diesen Anwendungsfall im C-Standard für structs eine Ausnahme existiert.
Wegen der strict-aliasing-Rule braucht man zumindest schon mal den Umweg über Werte statt Zeiger. D.h. entweder ein
memcpy
oder
union
. (Anmerkung: Kompiler implementieren
memcpy
als Kompiler-Intrinsic, d.h. bei zur Kompilierzeit bekannter Größe, zumindest bis zu einer gewissen Grenze, wird keine
memcpy
-Funktion aufgerufen.) Die Probleme beginnen, wenn man
memcpy
über mehrere
struct
-Elemente hinweg machen will (insbesondere ggf. über Padding hinweg). Von letzterem lässt Felix von vornherein die Finger.
Beste Beschäftigung damit hat Felix hier gefunden:
https://groups.google.com/a/isocpp.org/g/std-discussion/c/swgdeSqyTIw
Es scheint aus dem Standard so zu sein, dass man ein
union
braucht:
https://port70.net/~nsz/c/c11/n1570.html#6.5.2.3p6
https://timsong-cpp.github.io/cppwp/n4659/class.mem#20
https://timsong-cpp.github.io/cppwp/n4659/class.union#1
Felix sagt daher erst mal: Nein, ohne
memcpy
oder
union
gehts in C und C++ nicht (wenn man nicht Strict Aliasing deaktiviert). Der Standard definiert zwar "layout-compatible classes", aber es wurde vergessen festzulegen, was man mit denen überhaupt machen darf. Im Spezialfall von
unions
wurde es festgelegt.
>AFAICT the standard doesn't actually say what can and can't be done with layout-compatible types.
https://stackoverflow.com/questions/21956354/can-i-legally-reinterpret-cast-between-layout-compatible-standard-layout-types/22017275#22017275
Felix mag Sprach-Juristerei aber generell nicht.
Dazu relatiert gibt es auch diesen schönen Torvalds-Rant (Kernel benutzt insbesondere
-fno-strict-aliasing
):
https://lkml.org/lkml/2018/6/5/769
>Und wie oft berechnest du eine Konvolution über ein Bild, in dem jedes Pixel einen anderen polymorphen Typ hat? Das ist völlig an den Haaren herbeigezogen.
Das ist ein guter Punkt. Felix will aber anführen, dass er im Absatz darüber über seine Grafikgeschichten geschrieben hat und er das in dem Kontext anführen wollte (und nicht im Kontext von Polymorphie), d.h. dass man im Allgemeinen sehr wohl nicht nur elementweise Operationen durchführen will, und daher so etwas wie z.B.
std::for_each
+ Lambda nicht klappt (und einfach Parameterleiste länger machen klappt auch nicht).
Desweiteren hat Felix auch direkt die Beispiele aus
>Wenn es un-mathematischer sein soll: Sortieren, Mustersuche (mit variabel langem Muster/Regex), geordnetes Zusammenfügen zweier Arrays (wie bei Mergesort), Zusammenfügen im Reißverschlussverfahren von zwei Arrays ("zip"), Element entfernen, Duplikate entfernen, bestimmte Elemente duplizieren, Umordnen (z.B. Elemente bestimmten Typs ans Ende verschieben), Shiften eines Arrays um n Stellen mit Wraparound (braucht idR temporären Speicher), Array splitten.
nachgeschoben. Da kommt man mit elementweisen Operationen nicht weit und will auf den ganzen Arrays arbeiten. Da ist es dann mit elementweisen Operationen vorbei. Und wenns um Polymorphie geht: Einige der obigen Operationen brauchen eine Vergleichsfunktion, die dann bei Polymorphie eine virtuelle Funktion aufruft (z.B. Flächeninhalt von Shapes).