Hi,
Thanks for that ...
On Tue, 2007-02-20 at 13:51 +0900, Atsushi SAKAI wrote:
> > - ((struct sockaddr_in
*)&ifr.ifr_addr)->sin_family = AF_INET;
> > - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = inaddr;
> > + ((struct sockaddr_in *)((void *)&ifr.ifr_addr))->sin_family =
AF_INET;
> > + ((struct sockaddr_in *)((void *)&ifr.ifr_addr))->sin_addr =
inaddr;
bridge.c: In function 'brSetInetAddr':
bridge.c:344: warning: cast increases required alignment of target type
bridge.c:345: warning: cast increases required alignment of target type
bridge.c: In function 'brGetInetAddr':
bridge.c:381: warning: cast increases required alignment of target type
Okay, my understanding of this is that:
- The warning is caused by -Wcast-align
- Our problem is that we're casting between pointers to struct
sockaddr and struct sockaddr_in, which look like
struct sockaddr
{
unsigned short int sa_family;
};
struct sockaddr_in
{
unsigned short int sin_family;
uint16_t sin_port;
struct { uint32_t s_addr } sin_addr;
};
- Because of the uint32_t, struct sockaddr_in is required to be
aligned to a 4 byte boundary, whereas on ia64 struct sockaddr is
only required to be aligned to a 2 byte boundary
- If we look at in the context of struct ifreq, though:
struct ifreq
{
....
union {
struct sockaddr ifru_addr;
....
void *ifru_data;
} ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_data ifr_ifru.ifru_data
we see that because of the void pointer in the union, the struct
sockaddr is actually guaranteed to be aligned to 8 bytes and so the
warning can be ignored.
- I'd prefer to avoid the void pointer cast as someone could come
along and wonder whether the cast is hiding a genuine problem.
- So, I think I'll go ahead and do it this way instead:
- ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
- ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = inaddr;
+ ((struct sockaddr_in *)&ifr.ifr_data)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&ifr.ifr_data)->sin_addr = inaddr;
Cheers,
Mark.