Home > Enterprise >  Why the result of conditional / ternary operator may differ from if-else statements in some c type
Why the result of conditional / ternary operator may differ from if-else statements in some c type

Time:01-13

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

CodePudding user response:

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.

  • Related