I've got a question for all of the veteren C++ programmers out there.... I know that in_addr_t is a byte addressed value (representing an IPv4 address) however in debugging this code I was expecting a compile error ( scope of ipaddr declared in if statement would not extend to the else block):

if( in_addr_t ipaddr = inet_addr( s ) == -1 )
      {
         gpstk::Exception ie( "invalid IPv4 inet_addr : " + s );
         GPSTK_THROW(ie);
      }
      else
      {
         inetList.push_back( ipaddr ); 
      }

Instead, what I found is that this code compiles fine but instead pushes zero values onto inetList for every valid IPv4 address ( s == "" for instance).

If I parenthesize ( in_addr_t ipaddr = inet_addr( s ) ) then I will get the expected compile error and if I declare in_addr_t ipaddr; outside of the if-else statement then everything works as expected... truth be told I understand the fixes a bit more than the problem itself as it seems to me that the declaration and assignment of in_addr_t ipaddr = inet_addr( s ) should either be out of scope (and thus result in a compile error) or should work correctly; however not incorrectly represent the value of ipaddr as zero.

Any thoughts?

Dani AI

Generated

The symptom is explained by two simple facts: operator precedence and the C++ scoping rules for an if-init. The expression in the condition is parsed so the equality comparison happens first and its boolean result is used to initialize the declared variable. That yields 0 or 1 (hence the “zero values”), and because a name introduced by an if-init is in scope through the else branch there is no compile error. See the C++ if-statement and operator precedence notes for the formal rules: if statement and operator precedence.

Parenthesizing the declaration changes how the parser must interpret the token sequence, so the compiler rejects it: a parenthesized declaration cannot be treated as an expression to compare, and the grammar for the condition does not allow that mix. This is why adding parentheses produced a compile error for while the unparenthesized form compiled but did the wrong thing.

Two practical fixes and a robustness tip:

  • Separate the parse and the test: first obtain the address value into a named variable, then compare it.
  • Prefer modern parsing functions. inet_addr can return INADDR_NONE which collides with the legit address 255.255.255.255; use inet_aton or inet_pton instead.

Example (using inet_pton):

struct in_addr a;
if (inet_pton(AF_INET, s.c_str(), &a) != 1) {
/ handle invalid address /
} else {
inetList.push_back(a.s_addr);
}

This avoids the precedence/assignment pitfall and gives an unambiguous success/failure result (see the inet_pton and inet_addr manual pages for details). Credit to for spotting the boolean-initializer behavior and for noting the scope rules.

Recommended Answers

All 3 Replies

I believe (but since I'm not familiar with IP thingies, I'm not sure) that you are assigning a bool here: in_addr_t ipaddr = inet_addr( s ) == -1 Is the same as in_addr_t ipaddr = (inet_addr( s ) == -1) So you should write: (in_addr_t ipaddr = inet_addr( s )) == -1 but it gives you compile error, so simply try to make in_addr_t outside if statement.

And also, I believe if you declare something inside if (here) it exists in else?

I guess I confused as to why a compile error isn't generated in either circumstance... shouldn't in_addr_t ipaddr be out of scope regardless?

It's not a scope error: ipaddr is in scope from if clause to the end of else clause.
See prev post: you initialize ipaddr by (inet_addr(s) == -1) - it's eaual to false, so ipaddr == 0 after conversion false to in_addr_t.
You should write:

if( in_addr_t ipaddr = inet_addr(s), ipaddr == -1 )
{
    gpstk::Exception ie( "invalid IPv4 inet_addr : " + s );
    GPSTK_THROW(ie);
}
else
{
    inetList.push_back( ipaddr ); 
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.