-1

Here is my code:

// defs string untrusted_ip; const char * get_env (const char *name, const char *envp[]); string User::getCommonname(void); void User::setStatusFileKey(string); void User::setKey(string); // 1 if( get_env ( "untrusted_ip", envp ) !=NULL ){ newuser->setStatusFileKey(newuser->getCommonname() +string ( "," ) + untrusted_ip + string ( ":" ) + get_env ( "untrusted_port", envp ) ); newuser->setKey(untrusted_ip + string ( ":" ) + get_env ( "untrusted_port", envp ) ); }else{ newuser->setStatusFileKey(newuser->getCommonname() +string ( "," ) + untrusted_ip); newuser->setKey(untrusted_ip); } // 2 newuser->setStatusFileKey(newuser->getCommonname() +string ( "," ) + untrusted_ip + get_env ( "untrusted_ip", envp ) != (const char*)NULL ? string ( ":" ) + get_env ( "untrusted_port", envp ) : string("") ); newuser->setKey(untrusted_ip + get_env ( "untrusted_ip", envp ) != (const char*)NULL ? string ( ":" ) + get_env ( "untrusted_port", envp ) : string("") ); 

modified from https://salsa.debian.org/debian/openvpn-auth-radius/-/blob/master/radiusplugin.cpp#L446

block 1 and 2 seems to be equal but 1 works as expected while 2 does not work (seems not executing, for break point is not triggered).

What is the core difference between the two blocks of codes?

Also, only get_env ( "untrusted_ip", envp ) != (const char*)NULL in conditional operator can pass compilation while if( get_env ( "untrusted_ip", envp ) !=NULL ) is possible. What is the reason and are the two problems connected?

P.S. I am using gcc/g++ 10.2.1

6
  • Read about operator's precedence and look carefully on 2nd version. Commented Jan 13, 2023 at 11:40
  • 2
    I would add extra parenthesis... Commented Jan 13, 2023 at 11:41
  • 4
    both are equally unreadable Commented Jan 13, 2023 at 11:41
  • the conditional operator is in general not a drop in replacement for an if else. With T x = E1 ? E2 : E3; the relation and possible conversions between E2 and E3 matter to determine the type of the right hand side of =. With if (E1) x = E2; else x = E3; relations between E2 and E3 are irrelevant. As a result x can potentially be something entierly different Commented Jan 13, 2023 at 11:42
  • 1
    OT: NULL is the old C-compatibility macro for null pointers, in C++ use nullptr. Also don't call get_env multiple times, call it once and store the result to be reused. And since you have common code in both branches (the getCommoName() etc.) pull it out to also store in a common variable that can be used and reused. Commented Jan 13, 2023 at 11:44

1 Answer 1

1

It's an operator precedence issue.

The additions operator + have higher precedence than != so the expression is equivalent to (slightly rewritten to make it easier to see):

auto result = newuser->getCommonname() +string ( "," ) + untrusted_ip + get_env ( "untrusted_ip", envp ); newuser->setStatusFileKey( result != (const char*)NULL ? string ( ":" ) + get_env ( "untrusted_port", envp ) : string("") ); 

This is one of the many cases where the conditional expression makes the code not only harder to read and understand, but also makes it wrong.

The if else version is much easier to read and understand, and correct.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.