SKi
SKi

Reputation: 8476

Is it safe to assign struct value by using pointer

I have the following struct:

struct foo
{
   int  a;
   char b;
};

It is stored to memory and pointer to it can be unaligned (odd address).

So, is this safe?:

const struct foo a = *((struct foo*)char_ptr); 

I am worrying, because the integer member of the source struct can be in odd address. In some systems reading of (multi byte) integer from odd adderess causes problems.

EDIT: For avoiding off-topic commenting about usage of const, I did remove a const from the code. (I never cast const pointer to non-const pointer, even in this case where it should not cause any problems)

And more about context of problem: This kind of structure is part of protocol frame. And it can be in any offset inside the frame. In the real code the struct have __attribute__((packed)) attribute. But that probably not change the answer?

Anyway, I could use memcopy and non-const a for solving the problem. But I would like to use the assingment, because it seems to be more elegant way (if it is safe).

Upvotes: 2

Views: 642

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 223702

No, it is not safe, unless you know the pointer has the alignment required for the structure.

Here are some ways to know the pointer has the necessary alignment:

  • The pointer was originally a pointer to this structure type before it was converted to a pointer to char.
  • The pointer is a result of a memory allocation routine (such as malloc) that guarantees the address returned is suitably allocated for any use (which malloc does guarantee).
  • The pointer has been calculated from one of the above in a way that preserves the desired alignment.
  • You convert the pointer to a uintptr_t and test its alignment, provided this is supported by your C implementation.
  • Your C implementation (particularly the OS and processor) permits unaligned access to objects of the type in the structure.

If you do not know the pointer has the necessary alignment, then you should not access the structure through a converted pointer. Instead, you can define a new structure and use memcpy to copy from the pointer-to-char into the new structure.

Upvotes: 1

Art
Art

Reputation: 20402

If you get your data from a source where the pointer to the data isn't necessarily aligned, the only safe thing you can do is memcpy and hope that your complier isn't "smart" and pretends that the misaligned pointer is actually aligned and the memcpy can be optimized (there are several older versions of gcc that have this bug, requiring you to write a custom memcpy function that's not called memcpy). Depending on you architecture you can get away with improperly aligned access, but it will almost certainly be slower, sometimes even emulated through kernel traps.

A side anecdote: This is usually a problem in network stacks in operating systems where the odd size of the ethernet header makes the IP header unaligned and if the hardware doesn't have the ability to misalign the received packets (some DMA engines can only write data on 4 byte boundaries), this requires the whole headers (or the whole packet) to be copied once more in software.

Upvotes: 1

anishsane
anishsane

Reputation: 20980

See Data structure padding. On most systems, the structure will be aligned & internal member addresses will be aligned wrt their respective sizes, while malloc'ing itself.

If you manually create a memory pool & use some section within that to store your struct object, then compiler will not guarantee you alignment, but if you use malloc to create the struct object, it is generally compiler's headache, to give you aligned addresses, with padding if required between struct elements.

Upvotes: 2

Related Questions