EmbDev.net

Forum: ARM programming with GCC/GNU tools Please help in solving the warning "cast increases required alignment of target type"


von Karthik C. (karthik_c)


Rate this post
useful
not useful
I have two structures as below

Code:

struct prefix
{
   u_char a;
   u_char b;
   u_char c;
   u_char d;
   u_char e[4];
};

struct in_addr
{
   union{
     u_int8_t addr8[16];
     u_int16_t addr16[8];
     u_int32_t addr32[4];
   } in6;
}

When I used the above structures as a function argument as below
.....
.....
log(.......,(struct in_addr*)p->addr32,......); // where p is a pointer 
to structure prefix
.....
.....

/* log function accepts variable arguments and the argument "struct 
in_addr*)p->addr32" is one of such variable arguments. */

at that point, I am getting the warning as "cast increases required 
alignment of target type".

Googled for solution but very confused among "_attribute_ ((packed));" 
and "_attribute_ ((alligned) (x)) ;", which one to use and why?

Please help me

von kbuchegg (Guest)


Rate this post
useful
not useful
There seems to be something seriously wrong


You tell the compiler

(struct in_addr*)p->addr32

that is:
  take p    (whcih is a pointer to a prefix object)
  use it, as if it were a pointer to an in_addr
  and fetch the addr32 member.


Now.
If p is in reality a pointer to an prefix object, it points to an 
object, which looks like this

struct prefix
{
   u_char a;
   u_char b;
   u_char c;
   u_char d;
   u_char e[4];
}

what is the size of such an object, how big is it?
Well, guesses are, that it has a size of 8. a, b, c, d account for 4 
bytes, plus the 4 bytes for e makes 8.
(But better check that! It may be, that the compiler inserted some 
padding bytes!)


So p points to something that uses 8 Bytes in memory.

Now you tell the compiler to assume, that that something in memory is an 
in_addr, which looks like this


struct in_addr
{
   union{
     u_int8_t addr8[16];
     u_int16_t addr16[8];
     u_int32_t addr32[4];
   } in6;
}


How big is that?
Let us just concentrate on the addr32 member. It is an array of 4 
elements, each one beeing an u_int32_t. Well u_int32_t is not a standard 
C Datatype, but guesses are that the notation means: unsigned int with 
32 bits.
Well an 32 bit integer type means 4 bytes. And since there are 4 of 
them, that means the whole addr32 member has a size of at least 16 
bytes.

But that doesn't fit!
p points to something that has a size of 8 bytes and you want to trick 
the compiler into believing that in reality it has 16 bytes.


Hmmm.
If you ask me, there seems to be something seriously wrong.

von Markus F. (mfro)


Rate this post
useful
not useful
kbuchegg wrote:
> But that doesn't fit!
> p points to something that has a size of 8 bytes and you want to trick
> the compiler into believing that in reality it has 16 bytes.
>
>
> Hmmm.
> If you ask me, there seems to be something seriously wrong.

That's a pretty nice explanation, but unfortunately it's not the reason 
for the warning the thread starter experienced. The problem described 
might be an issue, but it's not the cause of the warning.

It's perfectly legal in C to dereference any pointer to an object of 
small size through a cast pointer to a larger object type. Usually, 
there is no warning issued, the compiler just takes the pointer, 
dereferences it and accesses the memory "behind" the original object 
regardless if it's meaningful or not.

The reason for the warning "cast increases required alignment of target 
type" is caused by the platform architecture requiring 32 bit variables 
to reside on even (or even "doubly even") addresses. The first struct 
can live at any odd or even address, the second one has limitiations. 
Accessing the first structure cast to the type of the second could cause 
a misalignment exception (or whatever the platform does when accessing 
data through misaligned pointers).

If you want to get rid of the warning (and runtime errors that possibly 
result from the potential misalignment),  you'll need to adjust the 
alignment requirements of the first struct identical to those of the 
second.
You could do that by appending
1
__attribute__ ((aligned (4)))
 to the structure definition (gcc-specific, not portable) or by nesting 
the structure into a union with another element (which you don't need to 
use, it just must be there) that has the same alignment requirements 
than the other structure - this would be portable.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.