As part of a function that receives a struct ifreq *ifr
argument, if I declare struct sockaddr_in name;
, the program compiles, but if I name the variable struct sockaddr_in ifr_addr;
, it fails with the following error:
code.c:244:24: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
struct sockaddr_in ifr_addr;
^
code.c:244:24: error: expected expression before ‘.’ token
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1
The ifreq
struct is declared as below. I know that the struct has a field with the same name than the problematic variable. How is that a problem in C?
struct ifreq {
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char *ifr_data;
};
};
When you get an error like that, it almost invariably means that a header, in this case probably one of the system headers, has defined a macro with the same name as you chose for your variable, but with an expansion that is not valid as an identifier.
You wouldn't see a problem if the header defines:
#define ifr_addr pwr_address
You do see a problem if, as you note in a comment, the expansion (in include/uapi/linux/if.h
, near line 258) is:
#define ifr_addr ifr_ifru.ifru_addr
The macro is meant to make it easier to access elements of a union without having to specify the union member name each time. At times like this, you find yourself asking — was it worth it? (I see this in the code base I work on daily — a lot. It's hard, sometimes, to work out what the code is accessing.)
Although it would be possible to use:
#undef ifr_addr
before defining your own variable with that name, doing so is treading on thin ice. It's best to accept that the name is preempted and use something else, annoying though it is. A possibility is to use ifr_srcaddr
, to match/contrast ifr_dstaddr
.