Copia struttura in array di BYTE

di il
3 risposte

Copia struttura in array di BYTE

Ciao a tutti, vorrei poter simulare un invio di dati tramite rete e per fare questo ho definito le seguenti strutture.

typedef struct Data {
   	int valid;
   	double value;
} Data;

typedef struct Message {
   	int id;
   	int size;
   	int nr;
	Data* data;
} Message;

Per l'invio vorrei copiare tutte le informazioni all'interno di un array di BYTE.

typedef unsigned char BYTE;

Di seguito ho messo per comodità tutto dentro alla funzione main.

Anche i dati di input sono in questo caso dei semplici dati di esempio.

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

int main() {
   	int sz = 5;
   	int id = 1;
   	int i;
   	
   	Data* input = malloc(sizeof(Data) * sz);
	
    for (i = 0; i < sz; i++) {
		input[i].valid = 1;
		input[i].value = (double)i;
	}

	int bufferSize = (sizeof(int) * 3) + (sizeof(Data) * sz);
	BYTE* buffer = malloc(sizeof(BYTE) * bufferSize);
    memcpy(buffer, &id, sizeof(int));
    memcpy(buffer + sizeof(int), &bufferSize, sizeof(int));
    memcpy(buffer + (sizeof(int) * 2), &sz, sizeof(int));
    memcpy(buffer + (sizeof(int) * 3), input, sizeof(Data) * sz);
    
    printf("Input data\nid: %d\nsize: %d\nnr: %d\n", id, bufferSize, sz);
	
	for (i = 0; i < sz; i++)
		printf("input[%d].valid: %d\ninput[%d].value: %lf\n", i, input[i].valid, i, input[i].value);

    printf("\nOutput data\n");
     
	// test
	Message* msg = (Message*)buffer;
    printf("id: %d\n", msg->id);
    printf("size: %d\n", msg->size);
    printf("nr: %d\n", msg->nr);
    
    // this way doesn't work
    // for (i = 0; i < sz; i++)
    //     printf("output[%d].valid: %d\noutput[%d].value: %lf\n", i, msg->data[i].valid, i, msg->data[i].value);
    
    Data* output = malloc(sizeof(Data) * sz);
    output = memcpy(output, &msg->data, sizeof(Data) * sz);
    
    for (i = 0; i < sz; i++)
		printf("output[%d].valid: %d\noutput[%d].value: %lf\n", i, output[i].valid, i, output[i].value);
		
	free(output);
	free(buffer);
	free(input);
}

Il mio problema si presenta quando cerco di estrarre i valori contenuti in data, sezione test. Purtroppo queste informazioni sembrano non poter essere ricostruite, ne per mezzo di un cast, e neppure copiando le informazioni in un altro array dinamico dello stesso tipo e dimensione. Però tutte le altre informazioni sono disponibili e corrette.

Non riesco a capire dove sto sbagliando. Potreste darmi una mano? 

Vi ringrazio.

3 Risposte

  • Re: Copia struttura in array di BYTE

    Quando serializzi una struttura, il memcpy fallo dalla struttura stessa (Message) al buffer (e viceversa)  per tutta la sizeof(struttura). I compilatori usano il padding per rendere il codice più veloce. Se vuoi forzare la dimensione della struttura a quella che ti aspetteresti, puoi mettere l'attributo __attribute__ ((packed)) in GCC

  • Re: Copia struttura in array di BYTE

    Quindi in sostanza dovrei adottare una soluzione del genere?

    int main() {
    
    	// ...
    
    	Message msg;
    	msg.id = id;
    	msg.size = 0;
    	msg.nr = sz;
    	msg.data = malloc(sizeof(Data) * msg.nr);
    	for (i = 0; i < msg.nr; i++) {
    		msg.data[i].valid = 1;
    		msg.data[i].value = (double)i;
    	}
    
    	int bufferSize = sizeof(msg);
    	msg.size = bufferSize;
    	BYTE* buffer = malloc(sizeof(BYTE) * bufferSize);
    	memcpy(buffer, &msg, bufferSize);
    	
    	// ...
    }

    Questa riga

    int bufferSize = sizeof(msg);

    però mi restituisce la dimensione della struttura, e non tiene conto della dimensione dell'array dinamico data.

    Come dovrei fare per calcolare la dimensione esatta per il buffer?

  • Re: Copia struttura in array di BYTE

    Scusa, non avevo capito bene cosa volessi fare

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Data {
       	int valid;
       	double value;
    } Data; // size = 16 (due double da 8 per il padding)
    
    typedef struct Message {
       	int id;
       	int size;
       	int nr;
    	Data data[]; // variable length array - obbligatoriamente ultimo
    } Message;
    
    int main(){
       	int sz = 5, id = 1, i;
       	
       	Data input[sz];
        for (i = 0; i < sz; i++) {
    		input[i].valid = 1;
    		input[i].value = (double)i;
    	}
    	
        printf("Input data\nid: %d\nsize: %d\nnr: %d\n", id, (int)sizeof(input), sz);	
    	for (i = 0; i < sz; i++)
    		printf("input[%d].valid: %d\ninput[%d].value: %f\n", i, input[i].valid, i, input[i].value);
    		
    	Message * msg = (Message *)malloc(3*sizeof(int) + sizeof(input));
    	msg->id = id;
    	msg->size = sizeof(input);
    	msg->nr = sz;
    	memcpy(msg->data, &input, sizeof(input));
    
        printf("\nOutput data\n");
        for (i = 0; i < sz; i++)
             printf("output[%d].valid: %d\noutput[%d].value: %lf\n", i, msg->data[i].valid, i, msg->data[i].value);	
    
        return 0;
    }
Devi accedere o registrarti per scrivere nel forum
3 risposte