Google Interview Question
Software Engineer / DevelopersCountry: United States
Interview Type: In-Person
sending in network byte order and receiving in host byte order i.e
htons() and ntohs will take care of endinness ?
@a.bharthan: yes. Although some protocols may choose to pick different endianness rules, of course.
@eugene...just wondering, whether we could use unions here to align the "item" object size to unsigned long(or uint64_t) . something like this:
union item_aligned{
struct item{
X x;
Y y;
Z z;
} item;
uint64_t for_aligning[some array size here];
}
You would need a union on each element of the struct and not on the struct itself. I assume that the struct is already properly aligned on an 8-byte boundary.
I've never tried this kind of union technique before, but I don't immediately see a reason it wouldn't work. Still, somehow I feel just a little bit safer going with the explicitly padded structs. And I should emphasize I don't feel safe with the structs either. You really should follow the advice in my last paragraph about the proper way to do things. Have an airtight specification that tells you the exact format of each byte, and send the data as a good ol' 1D array of bytes. Or take the advice of someone else here and use XML (if that's an option for you, given that it will take so much more space and hence bandwidth).
I think padding is done automatically unless specified other wise
stackoverflow.com/questions/4306186/structure-padding-and-structure-packing
Padding is certainly done automatically. It can, however, be done automatically in different ways on different machines. The padding is not guaranteed to be done in a way that would be consistent across different machines. If you declare the same struct on two different machines, you can't rely on it to be padded in the same way on both.
What about using plain text or XML - a sequence of 8-bit characters, ints and longs are sent as decimal numbers.
Plain and simple and does not need the knowledge of architectures (well, each side knows its own, but apart from that).
I know that this is not the most efficient way but the difference is not much (if you add padding)
There's a huge size difference. And yes, this is often how it's done, when you don't need to use a binary format.
All data send/received using the standard APIs use the Network byte order.
So there should not be a problem and we need no special handling.
sendto as shown above takes a void pointer, so it can't even know what primitives are in your struct. Therefore, the shown API can't order primitives correctly, or align them correctly.
There are always problems of portability, endianness, and alignment, and you need to handle them. Either the client will need to do the required manipulations and send the server the structure formatted in a way that's properly aligned for the server, or the server can be responsible for knowing the format in which the struct will be received from the client, and using bit masking and shifting to correctly read the structure if it's misaligned or has the wrong endianness.
If you can change your structure definition, you could insert dummy fields into your structure that you never touch but that are there to ensure that every field is aligned in such a way that it will be readable on (maybe almost) any machine. Usually, aligning every primitive to an offset that's a multiple of its size (for fixed-size arrays, the size of the base primitive) tends to be readable on machines. The explicit padding also tries to ensure that the padding strategy is consistent across machines. Also, it's very important to use types of specified size, e.g. int32_t instead of int. You want to make sure the size of a primitive does not differ from the client to the server. So you could make the struct be
You also need to handle endianness. You either need to send data to the server with the right endianness, or the server can be responsible for converting to the right endianness if needed.
- eugene.yarovoi September 16, 2012To be really sure you've achieved interoperability, you need a more airtight technique. The idea is to not use the struct at all (because how that's implemented in memory is not guaranteed by the standard), and to use a byte array instead.
To take this approach, one makes a specification which specifies which values are contained at what byte offsets, exactly how many bytes each value takes up, and what endianness they're stored in. Then code must be written that correctly parses a byte stream meeting this specification. This may involve lots of cases, e.g. if (bigEndianMachine) { ... }