Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
7
of 7 vote

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

uint8_t name[15]; //at 0-byte mark. chars are always aligned.
uint8_t padding1[1]; //at 15-byte mark
uint32_t price; //at 16-byte mark. Aligned!
uint8_t padding2[4]; //at 20-byte mark.
int64_t ID; //at 24byte mark, aligned!
uint8_t type[8]; // at 32-byte mark. chars are always aligned.

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.

To 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) { ... }

- eugene.yarovoi September 16, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

sending in network byte order and receiving in host byte order i.e
htons() and ntohs will take care of endinness ?

- a.bharthan September 16, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@a.bharthan: yes. Although some protocols may choose to pick different endianness rules, of course.

- eugene.yarovoi September 16, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

thanks

- a.bharthan September 16, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@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];
}

- Dharam September 18, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

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).

- eugene.yarovoi September 19, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think padding is done automatically unless specified other wise
stackoverflow.com/questions/4306186/structure-padding-and-structure-packing

- Anonymous December 23, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

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.

- eugene.yarovoi December 23, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

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)

- Selmeczy, Péter September 17, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

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.

- eugene.yarovoi September 17, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

"the difference is not much" - can often be a factor of 10 or more

- Anonymous September 19, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

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.

- anon.coder September 16, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

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.

- eugene.yarovoi September 16, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

what if it had been (struct item*) instead of void*

- a.bharthan September 16, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Simply casting your data to struct item* wouldn't help you (if that's what you're asking), as the API function still accepts void*

- eugene.yarovoi September 16, 2012 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More