Actual total size of structure elements

I have to write an array of structure data to the hard drive:


struct Data {
  char cmember;
  /* padding bytes */
  int  imember;  
};

AFAIK, most of compilers will add some padding bytes between cmember and imember members of Data, but I want save to file only actual data (without paddings).
I have next code for saving Datas array (in buffer instead of file for simplification):


bool saveData(Data* data, int dataLen, char* targetBuff, int buffLen)
{
  int actualLen = sizeof(char) + sizeof(int); // this code force us to know internal
                                              // representation of Data structure
  int actualTotalLen = dataLen * actualLen; 
  if(actualTotalLen > buffLen) {
    return false;
  }

  for(int i = 0; i &lt dataLen; i++) {
    memcpy(targetBuff, &data[i].cmember, sizeof(char));
    targetBuff += sizeof(char);
    memcpy(targetBuff, &data[i].imember, sizeof(int));
    targetBuff += sizeof(int);
  }
  return true;
}

CAN you see of As, I of the calculate Actual Primary size bed of the Data a struct with the below code: int actualLen = sizeof(char) + sizeof(int). Is there any alternative to this? (something like int actualLen = actualSizeof(Data))

PS this is synthetic example, but I think you understand idea of ​​my question ...

+3
source share
12 answers

. < < ,

myfile << mystruct.member1 << mystruct.member2;

< < < < < <, :

myfile << mystruct;

, :

myfile << count;
for (int i = 0; i < count; ++i)
    myFile << data[i];

IMO , memcpy, , . - Google , .

+8

.

.

++:

#pragma pack(push)
#pragma pack(1)

struct PackedStruct {
    /* members */
};

#pragma pack(pop)

. , . , .

, , , .

+3

. , , :

/* GNU has attributes */
struct PackedData {
    char cmember;
    int  imember;
} __attribute__((packed));

/* MSVC has headers and #pragmas */
#include <pshpack1.h>
struct PackedData {
    char cmember;
    int  imember;
};
#include <poppack.h>

, . ++, , , :

template <typename T>
std::ostream& encode_to_stream(std::ostream& os, T const& object) {
    return os.write((char const*)&object, sizeof(object));
}

template <typename T>
std::istream& decode_from_stream(std::istream& is, T& object) {
    return is.read((char*)&object, sizeof(object));
}

template<>
std::ostream& encode_to_stream<Data>(std::ostream& os, Data const& object) {
    encode_to_stream<char>(os, object.cmember);
    encode_to_stream<int>(os, object.imember);
    return os;
}
template <>
std::istream& decode_from_stream<Data>(std::istream& is, Data& object) {
    decode_from_stream<char>(is, object.cmember);
    decode_from_stream<int>(is, object.imember);
    return is;
}

, POD, . . , , , endianess, versioning . , , , , :

class Archive {
protected:
    typedef unsigned char byte;
    void writeBytes(byte const* byte_ptr, std::size_t byte_size) {
        m_fstream.write((char const*)byte_ptr, byte_size);
    }

public:
    template <typename T>
    void writePOD(T const& pod) {
        writeBytes((byte const*)&pod, sizeof(pod));
    }

    // Users are required to specialize this to use it.  If it is used
    // for a type that it is not specialized for, a link error will occur.
    template <typename T> void serializeObject(T const& obj);
 };

 template<>
 void Archive::serializeObject<Data>(Data const& obj) {
     writePOD(cmember);
     writePOD(imember);
 }

, , . , , . writePOD, , , -.

+2

, .

, " Google" Boost.Serialization .

/ .

, . , LZW, / , .

+2

#pragma pack . #pragma options align=packed - .

+1

, : int actualLen = sizeof (char) + sizeof (int). ?

, ++.

, . , Graeme Coincoin, .

+1

IIUC, , , . . #pragma pack - .

:

  • sizeof (char) == 1, ,

  • offsetof()

  • Data targetBuff (.. ) - . , , .
+1

pragma, ,

struct Data {
  int  imember;
  char cmember;

};
+1

, , , ( ), . , :

& ;
& ; double
& ; long long
& ; long
& ; float
& ; int
& ; short
& ; char
& ;

, , .

, , ( ), :

struct Data
{
    int     imember;
    char    cmember;
    /* padding bytes here */
};

, , ( API , , ).

+1

@Coincoin, . - ,

#define STRUCT_ELEMENTS  char cmember;/* padding bytes */ int  imember; 
typedef struct 
{
    STRUCT_ELEMENTS 
}paddedData;

#pragma pack(push)
#pragma pack(1)

typedef struct 
{
    STRUCT_ELEMENTS 
}packedData;
#pragma pop

;

sizeof(packedData);
sizeof(paddedData);

, , , . , .

+1

, . - , - , , . -, .

:

#undef  Data_MEMBERS  
#define Data_MEMBERS(Data_OP) \  
    Data_OP(c, char) \  
    Data_OP(i, int)  
#undef  Data_CLASS_DEFINITION  
#define Data_CLASS_DEFINITION(name, type) \  
    type name##member;  
struct Data {  
    Data_MEMBERS(Data_CLASS_DEFINITION)  
};  
#define Data_SERIAL_SIZER(name, type) \  
    sizeof(type) +  
#define Data_Serial_Size \  
    (Data_MEMBERS(Data_SERIAL_SIZER) 0)

.

0

, , , :

struct Data {  
   char cmember : 1;
   int  imember : 4;
};

, , 4 . .

:

  • Change the order of your members in size (first the largest). This is an old built-in trick to minimize holes.

  • Use Ada instead.

Code

type Data is record
    cmember : character;
    imember : integer;
end record;

for Data use record
    cmember at 0 range 0..7;
    imemeber at 1 range 0..31;
end record;

That you want.

0
source

Source: https://habr.com/ru/post/1721193/


All Articles