2016-10-17 2 views
2

Ich habe diese Struktur:Wie kann ich eine Struktur unbekannter Größe deklarieren?

struct   __attribute__((packed)) BabelPacket 
    { 
    unsigned  senderId; 
    unsigned  dataLength; 
    unsigned char data[0]; 
    }; 

Und es zu erklären, ich mache:

BabelPacket *packet = reinterpret_cast<BabelPacket *>(new char[sizeof(BabelPacket) + 5]); 
    packet->senderId = 1; 
    packet->data = "kappa"; 
    packet->dataLength = 5; 

Aber wenn ich ich habe diesen Fehler kompilieren:

error: incompatible types in assignment of ‘const char [6]’ to ‘unsigned char [0]’ 
    packet->data = "kappa"; 

      ^

Sie haben eine Idee, wie ich kann das tun ? Und ich muss diese Struktur über einen Socket senden, um das Objekt in meinem Server zurück zu bekommen, so dass ich nur C-Typen verwenden kann.

+6

Sie können nicht in Standard C++. – juanchopanza

+0

PD: https://StackOverflow.com/Questions/688471/Variable-Sized-Struct-c Suche nach einem besseren aber. –

+0

Dies funktioniert in C ([wie folgt] (http://stackoverflow.com/a/19293671/335858)), aber nicht in C++. – dasblinkenlight

Antwort

-1

Wenn Sie bereit/erlaubt sind die unsigned char zu einem regelmäßigen char zu ändern, können Sie strcpy verwenden:

#include <iostream> 
#include <stdio.h> 
#include <string.h> 

struct   __attribute__((packed)) BabelPacket 
{ 
    unsigned  senderId; 
    unsigned  dataLength; 
    char data[0]; // I changed this to char in order to use strcpy 
}; 

int main(){ 
    BabelPacket *packet = reinterpret_cast<BabelPacket *>(new char[sizeof(BabelPacket) + 5]); 
    packet->senderId = 1; 
    // Copy the string. Add NULL character at the end of 
    // the string to indicate its end 
    strcpy(packet->data, "kappa\0"); 
    packet->dataLength = 5; 

    // Verify that the string is copied properly 
    for (int i=0;i<packet->dataLength;++i){ 
    std::cout<<packet->data[i]; 
    } 
    std::cout<<std::endl; 

    return 0; 
} 

Beachten Sie, dass dies nur funktioniert, wenn data am Ende des struct ist, da sonst kein zusammenhängender Speicher zur Zuweisung data. Wenn ich die Reihenfolge der Elemente wechseln zu:

struct   __attribute__((packed)) BabelPacket 
{ 
    unsigned  senderId; 
    char data[0]; // I changed this to char in order to use strcpy 
    unsigned  dataLength; 
}; 

die Ausgabe des obigen Code (anstelle von „Kappa“), wäre „a“.

Eine zuverlässigere Art und Weise, wenn Sie entschlossen sind, C-Arrays zu verwenden wäre, eine maximale Anzahl von Elementen zu übernehmen und das Array preallocate, das heißt:

#include <iostream> 
#include <stdio.h> 
#include <string.h> 

#define MAX_NUMBER_OF_CHARACTERS 5 // Many ways to do this, I defined the macro for the purposes of this example 

struct   __attribute__((packed)) BabelPacket 
{ 
    unsigned  senderId; 
    // I changed this to char in order to use strcpy. Allocate the 
    // max number + 1 element for the termination string 
    char data[MAX_NUMBER_OF_CHARACTERS+1]; 
    unsigned  dataLength; 
}; 

int main(){ 
    BabelPacket *packet = reinterpret_cast<BabelPacket *>(new char[sizeof(BabelPacket) + 5]); 
    packet->senderId = 1; 
    packet->dataLength = 5; 
    if (dataLength>MAX_NUMBER_OF_CHARACTERS){ 
    std::cout<<"String greater than the maximum number of characters"<<std::endl; 
    } 
    // Copy the string. Add NULL character at the end of 
    // the string to indicate its end 
    strcpy(packet->data, "kappa\0"); 

    // Verify that the string is copied properly 
    for (int i=0;i<packet->dataLength;++i){ 
    std::cout<<packet->data[i]; 
    } 
    std::cout<<std::endl; 

    return 0; 
} 

Dieser Code die korrekte Ausgabe erzeugt, und schützt Sie gegen Verstöße. Wie Sie sehen können, kann es ziemlich schnell unordentlich werden, weshalb ich empfehlen würde, dafür std::vector zu verwenden. Die dataLength kann dann automatisch als die Größe des Vektors abgerufen werden, und Sie sind immer gegen Überläufe geschützt.

+0

'char Daten [0];' Das ist in C++ nicht erlaubt. – juanchopanza

+0

@juanchopanza Ich benutze g ++ 5.4 und das funktioniert gut. –

+0

Ebenso funktioniert es gut mit clang 3.8 für mich auch. – nikaza

3

Wenn dies ein C-Programm war, liegt der Fehler darin, dass Sie versuchen, einem Array zuzuweisen, was nicht möglich ist. Sie können nur kopieren auf ein Array:

memcpy(packet->data, "kappa", 5); 

Beachten Sie auch, dass, wenn Sie die Daten wollen einen C-String sein, müssen Sie '\0' ein zusätzliches Zeichen für den String-Terminator zuzuordnen. Dann können Sie strcpy anstelle von memcpy oben verwenden. Oder strncpy, um höchstens eine bestimmte Anzahl von Zeichen zu kopieren, aber dann müssen Sie die Zeichenfolge möglicherweise manuell beenden.

Allerdings sollte dies in C++ überhaupt nicht funktionieren, es sei denn, Ihr Compiler hat es als Erweiterung.

+1

Lieber eine sicherere Alternative zu 'strcpy' bieten. –

+1

Ich denke, du meinst 'memcpy (packet-> data," kappa ", 5);' – juanchopanza

+0

@juanchopanza Stimmt, ich meine das. Danke –

0

Sie können keine literale Zeichenfolge auf diese Weise zuweisen. Sie müssen der Zeichenfolge zusätzlichen Speicher zuweisen und dann in den Datenzeiger kopieren.

Diese Lösung ist nur in Umgebungen anwendbar, in denen Arrays der Länge Null oder flexible Arrays unterstützt werden. In der Tat könnte eine bessere Lösung darin bestehen, den Sockets-Code in C zu schreiben und diese Schnittstelle zur Verwendung in C++ zu exportieren.

+0

'char Daten [0];' Das ist in C++ nicht erlaubt. – juanchopanza

+0

@juanchopanza Wenn man bedenkt, dass er Attribute verwendet, kann man davon ausgehen, dass er GCC verwendet, der es als Erweiterung unterstützt. –

+0

Das würde von Compilerflags abhängen. – juanchopanza

Verwandte Themen