2016-09-20 1 views
1
uint32_t u32 = 0; 
uint16_t u16[2]; 
static_assert(sizeof(u32) == sizeof(u16), ""); 
memcpy(u16, &u32, sizeof(u32)); // defined? 
// if defined, how to we access the data from here on? 

Ist dieses definierte Verhalten? Und wenn ja, welche Art von Zeiger können wir verwenden, um auf die Zieldaten nach dem memcpy zuzugreifen?memcpy von einem Typ zu einem anderen Typ. Wie gelangen wir später zum Ziel?

Müssen wir verwenden uint16_t*, denn das ist geeignet für die erklärt Art von u16?

Oder müssen wir uint32_t* verwenden, weil der Typ der Quelldaten (die Quelldaten kopiert von memcpy) uint_32 ist?

(persönlich interessiert in C++ 11/C++ 14. Aber eine Diskussion verwandter Sprachen wie C auch interessant wäre.)

+1

Ist es kompilieren? – wally

+0

Es tut jetzt :-) (Ich hatte ein '&' und einen anderen Tippfehler vergessen) –

+1

Versuchen Sie, die Endianz Ihrer CPU herauszufinden? –

Antwort

1

Die C++ Standard Delegierten Standard C:

Der Inhalt und die Bedeutung des Kopf <cstring> sind die gleichen wie die C-Standardbibliothek Kopf <string.h>.

Der C-Standard spezifiziert:

7.24.1/3 Für alle Funktionen in diesem Unterabschnitt wird jedes Zeichen interpretiert werden, als ob es den Typ unsigned char hatte (und damit jeder mögliche Objektdarstellung ist gültig und hat einen anderen Wert).

So, um Ihre Frage zu beantworten: Ja, das Verhalten ist definiert.

Ja, uint16_t* ist geeignet, da uint16_t der Typ des Objekts ist.


Nein, der Typ der Quelle spielt keine Rolle.

C++ -Standard spezifiziert nicht so etwas wie Objekt ohne deklarierten Typ oder wie es sich verhalten würde. Ich interpretiere das so, dass der effektive Typ die Implementierung für Objekte ohne deklarierten Typ definiert.

Auch in C spielt die Quelle in diesem Fall keine Rolle. Eine vollständigere Version des Zitats von C-Standard (Entwurf, N1570), die Sie besorgt sind, Hervorhebung von mir:

6,5/6 [...] Wenn ein Wert in ein Objekt kopiert wird, nicht deklarierten Typ mit mit memcpy oder memmove, oder wird als ein Array von Zeichentypen kopiert, dann ist der effektive Typ des modifizierten Objekts für diesen Zugriff und für nachfolgende Zugriffe, die den Wert nicht ändern, der effektive Typ des Objekts, von dem der Wert kopiert wird wenn es eins hat. [...]

Diese Regel gilt nicht, da Objekte in u16 erklärt haben Sie eine Art

+0

Eine kleine Folge: Der 'deklarierte Typ' eines Objekts, wenn es ein Objekt hat, kann sich niemals ändern? Und ein Objekt kann niemals einen "deklarierten Typ" verlieren oder gewinnen? Aber der "effektive Typ" kann sich unter bestimmten Umständen ändern? –

+1

@AaronMcDaid deklarierter Typ ändert sich nicht. Wenn Objekt den Typ deklariert hat, dann ist es auch der effektive Typ - und es ändert sich nicht. Ein gültiger Typ kann gewonnen oder geändert werden, wenn es keinen deklarierten Typ gibt. – user2079303

+0

Ich denke jetzt, dass ein großer Teil der Aliasing-Antworten auf andere Fragen zu Stack Overflow viel sinnvoller wäre, wenn diese Kommentare hier über "deklariert" und "effektiv" am Anfang jeder Antwort stehen würden. –

0

Ist das definiert behavio [u] r?

Ja. memcpy in einer Kapsel ist klar definiert und Sie haben sichergestellt, dass die Größenanpassung korrekt ist.

Müssen wir verwenden uint16_t*, denn das ist geeignet für den deklarierten Typ von u16?

Ja, natürlich. u16 ist ein Array von zwei uint16_t s, so dass es als solche zugegriffen werden muss. Der Zugriff darauf über ein uint32_t* wäre undefiniertes Verhalten durch die Strict-Aliasing-Regel.

Es spielt keine Rolle, was der Quellentyp ist. Wichtig ist, dass Sie ein Objekt vom Typ uint16_t[2] haben.


Auf der anderen Seite, diese:

uint32_t p; 
new (&p) uint16_t(42); 
std::cout << p; 

ist nicht definiertes Verhalten, weil nun ein Objekt eines anderen Typs, deren Lebensdauer gibt es bei &p beginnen hat und wir den Zugriff auf sie durch der falsche Typ.

+0

Eine Sache, die mich beunruhigt, ist, dass es Sätze im C-Standard gibt, die mir vorschlagen, dass der Typ "uint32_t" ist, zum Beispiel "[der Typ wird]] ... der effektive Typ des Objekts, von dem der Wert kopiert wird ... ". Ich habe keine Standarddokumente zur Hand, alles, was ich tun kann, ist Kopieren und Einfügen von Sachen, die ich online finde - ich fand diesen Satz hier: http://StackOverflow.com/Questions/30970251/what-is-the-effective -type-of-ein-objekt-geschrieben von-memset –

+0

@AaronMcDaid C++ ist nicht C. – Barry

+0

Außer, wenn C++ explizit angibt, dass es * C ist, in einigen Kontexten. (Siehe die Antwort von Benutzer2079303). –

Verwandte Themen