Kann ein Char-Array mit einem beliebigen Datentyp verwendet werden?

8

Die Funktion malloc() gibt einen Zeiger vom Typ void* zurück. Er weist Speicher in Bytes entsprechend dem als Argument übergebenen size_t -Wert zu. Die resultierende Zuweisung ist Rohbytes, die mit jedem Datentyp in C (ohne Casting) verwendet werden können.

Kann ein Array mit dem Typ char innerhalb einer Funktion deklariert werden, die void * zurückgibt, mit einem beliebigen Datentyp wie die resultierende Zuweisung von malloc ?

verwendet werden?

Zum Beispiel

%Vor%     
machine_1 21.07.2016, 17:20
quelle

3 Antworten

5

Der deklarierte Typ des statischen Objekts Array ist char . Der effektive Typ dieses Objekts ist der deklarierte Typ. Der effektive Typ eines statischen Objekts kann nicht geändert werden. Daher ist für den Rest des Programms der effektive Typ von Array char .

Wenn Sie versuchen, auf den Wert eines Objekts mit einem Typ zuzugreifen, der nicht mit dieser Liste kompatibel ist oder nicht, 1 , ist das Verhalten nicht definiert.

Ihr Code versucht mit dem Typ Array auf den gespeicherten Wert von int zuzugreifen. Dieser Typ ist nicht kompatibel mit dem Typ char und befindet sich nicht in der Liste der Ausnahmen. Daher ist das Verhalten nicht definiert, wenn Sie das Array mit dem int -Zeiger p :

lesen %Vor%

1 (Zitiert nach: ISO: IEC 9899: 201X 6.5 Ausdrücke 7)
Auf ein Objekt muss sein gespeicherter Wert nur durch einen L-Wert zugreifen  Ausdruck, der einen der folgenden Typen aufweist:
 - eine Art  kompatibel mit dem effektiven Objekttyp,
 - ein qualifizierter  Version eines Typs, der mit dem effektiven Objekttyp kompatibel ist,
 - ein Typ, bei dem es sich um den Typ mit oder ohne Vorzeichen handelt  effektive Art des Objekts,
 - ein Typ, der signiert oder unsigniert ist  Typ entsprechend einer qualifizierten Version des effektiven Typs der  Objekt,
- Ein Aggregat- oder Unionstyp, der eines der folgenden Elemente enthält:  vorgenannte Typen unter seinen Mitgliedern (einschließlich, rekursiv, a  Mitglied eines Unteraggregats oder einer enthaltenen Union) oder
- ein Zeichentyp.

    
2501 21.07.2016, 18:43
quelle
3

Nein, Sie können ein beliebiges Byte-Array wegen möglicher Ausrichtungsprobleme nicht für einen beliebigen Typ verwenden. Der Standard sagt in 6.3.2.3 Conversions / Pointer (betone meine):

  

Ein Zeiger auf ein Objekt oder einen unvollständigen Typ kann in einen Zeiger auf einen anderen umgewandelt werden   Objekt oder unvollständiger Typ. Wenn der resultierende Zeiger nicht korrekt für die Ausrichtung ausgerichtet ist   spitz zu Typ, das Verhalten ist nicht definiert . Andernfalls, wenn wieder zurück konvertiert wird   Das Ergebnis muss mit dem ursprünglichen Zeiger übereinstimmen.

Als char als kleinste Ausrichtungsanforderung können Sie nicht sicherstellen, dass Ihr char-Array für jeden anderen Typ korrekt ausgerichtet ist. Deshalb garantiert malloc, dass ein von malloc erhaltener Puffer (selbst wenn es ein void * ist) die größtmögliche Ausrichtungsbedingung hat, um jeden anderen Typ akzeptieren zu können.

Ich denke das

%Vor%

sollte für jeden Typ korrekt ausgerichtet sein, da es mit den größten Basistypen kompatibel ist (wie in 6.2.5 definiert). Ich bin mir ziemlich sicher, dass es für alle gängigen Implementierungen (gcc, clang, msvc, ...) funktionieren wird, aber leider konnte ich keine Bestätigung finden, dass der Standard es erlaubt. Im Wesentlichen wegen der strengen Aliasing-Regel, wie in 6.5 Ausdruck §7 definiert:

  

Auf einen gespeicherten Wert eines Objekts darf nur durch einen lvalue-Ausdruck zugegriffen werden, der eines von   die folgenden Typen:

     
  • ein Typ, der mit dem effektiven Objekttyp kompatibel ist,
  •   
  • eine qualifizierte Version eines Typs, der mit dem effektiven Typ des Objekts kompatibel ist,
  •   
  • ein Typ, bei dem es sich um den Typ mit oder ohne Vorzeichen handelt, der dem effektiven Typ von   Objekt,
  •   
  • ein Typ, bei dem es sich um den Typ mit oder ohne Vorzeichen handelt, der einer qualifizierten Version von   effektive Art des Objekts,
  •   
  • ein Aggregat- oder Unionstyp, der einen der oben genannten Typen enthält   Mitglieder (einschließlich rekursiv, ein Mitglied eines Unteraggregats oder enthalten Union) oder
  •   
  • ein Zeichentyp.
  •   

Also IMHO gibt es keine portable und standardkonforme Möglichkeit, einen benutzerdefinierten Zuordner zu erstellen, der malloc nicht verwendet.

    
Serge Ballesta 21.07.2016 18:30
quelle
-1

Wenn man das Grundprinzip des C89-Standards liest, besteht der einzige Grund, warum die Typ-Aliasing-Regeln existieren, darin, zu vermeiden, dass Compiler "Worst-Case-Aliasing-Annahmen" machen müssen. Das gegebene Beispiel war:

%Vor%

Wenn das Programm ein "char" -Array innerhalb einer Union erstellt, die etwas enthält, dessen Ausrichtung für jeden Typ geeignet ist, nimmt die Adresse davon und greift niemals auf den Speicher dieser Struktur zu, außer durch den resultierenden Zeiger, es sollte keinen Grund geben Aliasing-Regeln sollten Schwierigkeiten verursachen.

Es ist erwähnenswert, dass die Autoren des Standards erkannt haben, dass eine Implementierung gleichzeitig konform, aber nutzlos sein könnte; siehe die Begründung für C89 2.2.4.1:

  

Während eine mangelhafte Umsetzung wahrscheinlich ein Programm schaffen würde, das diese Anforderung erfüllt, aber trotzdem nutzlos ist, war der Ausschuss der Ansicht, dass ein solcher Einfallsreichtum wahrscheinlich mehr Arbeit erfordern würde, als etwas Nützliches zu machen. Der Sinn des Ausschusses ist, dass die Implementierer die Übersetzungsgrenzen nicht als die Werte von festverdrahteten Parametern verstehen, sondern als eine Reihe von Kriterien, anhand derer eine Implementierung beurteilt wird.

Obwohl diese spezielle Aussage in Bezug auf die Implementierungsgrenzen gemacht wird, ist die einzige Möglichkeit, die C89 als mit den vorausgehenden C-Dialekten im Entferntesten kompatibel zu interpretieren, sie als breiter anwendbar zu betrachten: Der Standard tut dies nicht versuche, erschöpfend alles zu spezifizieren, was ein Programm tun können sollte, aber er verlässt sich darauf, dass Compiler-Autoren einen gesunden Menschenverstand ausüben.

Die Verwendung eines zeichenartigen Arrays als Backing-Speicher eines beliebigen Typs, vorausgesetzt, man stellt sicher, dass Ausrichtungsprobleme behoben werden, sollte keine Probleme mit einem nicht stumpf geschriebenen Compiler verursachen. Der Standard hat nicht vorgeschrieben, dass Compiler-Autoren solche Dinge erlauben, weil sie keinen Grund sahen, von ihnen zu erwarten, dass sie etwas anderes tun. Leider haben sie nicht den Weg eingeschätzt, den die Sprache im 21. Jahrhundert gehen würde.

    
supercat 22.07.2016 21:19
quelle

Tags und Links