Die Regel für den effektiven Typ in C99 und C11 sieht vor, dass Speicher ohne deklarierten Typ mit einem beliebigen Typ geschrieben werden kann und dass beim Speichern eines Werts eines Nicht-Zeichen-Typs der effektive Typ des Speichers entsprechend festgelegt wird.Ist diese Verwendung der Effektivtyp-Regel streng konform?
Abgesehen von der Tatsache, dass INT_MAX weniger als 123456789 sein könnte, wäre die Verwendung der Regel für den effektiven Typ im folgenden Code streng konform?
#include <stdlib.h>
#include <stdio.h>
/* Performs some calculations using using int, then float,
then int.
If both results are desired, do_test(intbuff, floatbuff, 1);
For int only, do_test(intbuff, intbuff, 1);
For float only, do_test(floatbuff, float_buff, 0);
The latter two usages require storage with no declared type.
*/
void do_test(void *p1, void *p2, int leave_as_int)
{
*(int*)p1 = 1234000000;
float f = *(int*)p1;
*(float*)p2 = f*2-1234000000.0f;
if (leave_as_int)
{
int i = *(float*)p2;
*(int*)p1 = i+567890;
}
}
void (*volatile test)(void *p1, void *p2, int leave_as_int) = do_test;
int main(void)
{
int iresult;
float fresult;
void *p = malloc(sizeof(int) + sizeof(float));
if (p)
{
test(p,p,1);
iresult = *(int*)p;
test(p,p,0);
fresult = *(float*)p;
free(p);
printf("%10d %15.2f\n", iresult,fresult);
}
return 0;
}
Aus meiner Lektüre der Norm, alle drei Verwendungen der Funktion im Kommentar beschrieben sollte (mit Ausnahme der integer-Bereich Ausgabe) streng konform sein. Der Code sollte daher 1234567890 1234000000.00
ausgeben. GCC 7.2 gibt jedoch 1234056789 1157904.00
aus. Ich denke, wenn leave_as_int
0 ist, speichert es 123400000 zu *p1
, nachdem es 123400000.0f zu *p2
speichert, aber ich sehe nichts im Standard, das solches Verhalten autorisieren würde. Fehle ich etwas oder ist GCC nicht konform?
Mein Lesen des verknüpften Beitrags schlägt vor, dass Geschäfte den dynamischen Typ von Objekten ändern * mit einem deklarierten Typ * ist eine Erweiterung, aber ein solches Verhalten wird vom Standard für Objekte ohne deklarierten Typ [z. ein Zeiger, der von 'malloc()'] empfangen wird. Die Einhaltung des Standards würde erfordern, dass ein Compiler bestimmte pessimistische Annahmen in Fällen trifft, die oft unnötigen ineffizienten Code ergeben, und es wäre für Compiler sinnvoll, einen * nichtkonformen * Modus anzubieten, der dynamische/effektive Objekte nicht berücksichtigen würde In solchen Fällen zu ändernde Typen. – supercat
Sonst bin ich momentan nicht in der Datei gcc bugs registriert, obwohl ich mich vielleicht registrieren sollte. Ich bin mir jedoch nicht sicher, was als Abhilfe vorgeschlagen werden sollte, wenn das Verhalten nicht als konform beschrieben werden kann. Da die Einhaltung des Standards in einigen Fällen unnötigerweise die Optimierung behindern würde, kann es praktisch sein, einfach zu sagen, dass "-fno-strict-aliasing" für die vollständige Konformität erforderlich ist und dass "-fstrict-aliasing" nur mit Code verwendet werden kann, der niemals existiert recycelt Speicher. Leider würde dies bedeuten, dass Code, der den Speicher recyceln muss, ineffizient verarbeitet wird. – supercat