Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I noticed one unpleasant thing that happens with std::pair when tried to save it into binary file: std::pair is aligned to a word. It might be useful in terms of processor efficiency, but requires more storage space, so I want to switch align mode to 1-byte for std::pair. My compiler is MS VC++ 2012.
#include <iostream>
int main( )
struct S_a { double a; size_t b; };
#pragma pack(1)
struct S_wa { double a; size_t b; };
std::cout << sizeof( size_t ) << '\n'; // 4
std::cout << sizeof( double ) << '\n'; // 8
std::cout << sizeof( std::pair< size_t, size_t > ) << '\n'; // 8
std::cout << sizeof( std::pair< double, size_t > ) << '\n'; // 16 - bad
std::cout << sizeof( S_wa ) << '\n'; // 12 - good
std::cout << sizeof( S_a ) << '\n'; // 16
std::cout << sizeof( std::pair< double, double > ) << '\n'; // 16
I tried this, but it doesn't work:
#pragma pack(1)
typedef std::pair< double, size_t > Q;
std::cout << sizeof( Q ) << '\n'; // 16
–
–
The alignment of the two members is defined by the alignment in force when the template itself is defined, not just when it's used to instantiate an instance.
The Microsoft implementation of the STL uses the symbol _CRT_PACKING
to define the packing used for all STL components. By default the packing is set to 8. If you define this symbol yourself before including the header that defines std::pair
(<utility>
) you can theoretically override the packing and set your own.
Be aware of potential problems you may encounter calling libraries or other code that assumes the standard packing.
Sorry, the pack
pragma won't work for you in this situation. You could
#define _CRT_PACKING 1
#include <utility>
This can cause ALL SORTS of problems. One of which is that certain APIs, especially low-level ones, expect data to be aligned in a certain way. Not all of them are smart enough to deal with the situation where it's not; which could lead to unceremonious crashing.
If you really want the object to be serialised like this, handle the serialisation of std::pair<U,V>
yourself (example only):
template<typename U, typename V>
void paircpy(char *dest, const std::pair<U, V> &pair) {
memcpy(buffer, &pair.first, sizeof(U));
memcpy(buffer + sizeof(U), &pair.second, sizeof(V));
You would want to handle the special case for data types that don't memcpy
well.
What you really should do, for any serious project, is serialise objects in a portable way so that they're retrievable and elegantly handle things like floating point, different encodings for signed data types, pointers, arrays, STL containers and anything else where a simple dump of the object's memory is not possible or is insufficient.
Read the C++ FAQ and develop your own serialisation modules which are more than just dumping the in-memory representation of the object to file.
Alternatively, you can use a pre-packaged portable solution for serialising data types such as
Boost.Serialization
Google's Protocol Buffers
The XDR library
JSON or XML
–
–
Alright, totally different 'solution' that may or may not be a good idea, but hey if it works who am I to stop you from knowing. It comes with all of the same caveats as the other answers, but allows you to pick and choose your poisons.
Do a partial specialization of std::pair
for the types that you care about, using the pragma pack for that particular definition, ex. for char
and int
:
namespace std {
#pragma pack( /* ... whatever you want ... */ )
template<> struct pair<char,int> {
char first;
int second;
With the definition somewhere you can touch it, you can affect the packing. Again, this is only good if you're willing to do it for all relevant types, and keep in mind the caveats mentioned by the other posters.
and there's the small chance that the library you're using is crazy and decided to put more stuff in pair
that the rest of the lib depends on, but you probably don't need to worry about it
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.