The compiler produces this warning when I\'m working with some code which looks like -
....
for(p = res; p != NULL; p = p->ai_next) {
void *addr;
TLDR: This warning doesn't indicate an error in your code, but you can avoid it by using a poper c++ reinterpret_cast
(thanks to @Kurt Stutsman).
Explanation:
Reason for the warning:
sockaddr
consists of a unsigned short (usually 16 bit) and a char array, so its alignment requirement is 2. sockaddr_in
contains (among other things) a struct in_addr
which has an alignment requirement of 4 which in turn means sockaddr_in
also must be aligned to a 4 Byte boundary.For that reason, casting an arbitrary sockaddr*
to an sockaddr_in*
changes the alignment requirement, and accessing the object via the new pointer would even violate aliasing rules and result in undefined behavior.
Why you can ignore it:
In your case, the object, p->ai_addr
is pointing to, most likely is a sockaddr_in
or sockaddr_in6
object anyway (as determined by checking ai_family
) and so the operation is safe. However you compiler doesn't know that and produces a warning.
It is essentially the same thing as using a static_cast
to cast a pointer to a base class to a pointer to a derived class - it is unsafe in the general case, but if you know the correct dynamic type extrinsically, it is well defined.
Solution:
I don't know a clean way around this (other than suppress the warning), which is not unusual with warnings enabled by -Weverything
. You could copy the object pointed to by p->ai_addr
byte by byte to an object of the appropriate type, but then you could (most likely) no longer use addr
the same way as before, as it would now point to a different (e.g. local) variable.
-Weverything
isn't something I would use for my usual builds anyway, because it adds far too much noise, but if you want to keep it, @Kurt Stutsman mentioned a good solution in the comments:
clang++ (g++ doesn't emit a warning in any case) doesn't emit a warning, if you use a reinterpret_cast
instead of the c style cast (which you shouldn't use anyway), although both have (in this case) exactly the same functionality. Maybe because reinterpret_cast
explicitly tells the compiler: "Trust me, I know, what I'm doing" .
On a side Note: In c++ code you don't need the struct
keywords.