Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

c++ code review

Posted on 2011-10-13
35
Medium Priority
?
330 Views
Last Modified: 2012-05-12



    if (ad && (etag = strrcasestr_len(ad,strlen(ad),
                    "</XHTML-STRIPONREPLY>", 21))) {

here ad and etag are const char*

when the custom function strrcasestr_len returns NULL

will the expression evaluate to (ad && null)
0
Comment
Question by:Vlearns
  • 9
  • 8
  • 6
  • +2
31 Comments
 
LVL 7

Accepted Solution

by:
Bill Nolan earned 2000 total points
ID: 36966116
Yes.  It will always evaluate to (ad && etag).
0
 

Author Comment

by:Vlearns
ID: 36966122
i was afraid that it would evaluate to ad && true

since etag = something is always true

thats not the case right?
0
 
LVL 7

Expert Comment

by:Bill Nolan
ID: 36966152
Well, essentially what you are asking is if:

etag = NULL;

...will result in etag being non-null, which is clearly not the case.

Maybe you're not sure exactly what is being evaluated.  "If (var)" will check if the value of 'var' is non-null (not zero).  etag is a pointer, whose value is the address of a char.  If the strcase function returns 0, then that pointer's value will zero.

But to make sure you understand it exactly, set up some test conditions and step through it in the debugger.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:Vlearns
ID: 36966165
so will the following statement evaluate to true

if (x=0)

0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36966188
so will the following statement evaluate to true

if (x=0)


No.  That's the same as   if ( 0 )   which is essentially the same as    if ( false )
0
 
LVL 7

Expert Comment

by:Bill Nolan
ID: 36966195
No.

Maybe this will help:  The assignments will always be done before the comparisons.

A better question would be "does e get set to 1 in the following statement?"...

if (a > b && e = 1)

...And I am saying yes - though I suppose it is possible that it could depend on the compiler.  That is why I will often make a quick test myself when these things come up :)
0
 
LVL 7

Expert Comment

by:Bill Nolan
ID: 36966200
CORRECTION from my previous (why can't we edit a previous post?):

A better question would be "does e get set to 1 in the following statement when a is <= b?"...
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36966989
Hi,

@Slimfinger:
A better question would be "does e get set to 1 in the following statement?"...

if (a > b && e = 1)

...And I am saying yes ...


IMO that's not correct - if 'a' isn't greater than 'b' the expression 'e = 1' isn't executed. Further that sample doesn't compile because the left part of the '=' has to be an lValue but the 'a > b && e' compiles to a 'const' expression.

ZOPPO
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36967189

A better question would be "does e get set to 1 in the following statement?"...

On my computer, the code won't even compile.     foo.cpp:13: error: lvalue required as left operand of assignment

I have to change it to if ( a > b && ( e = 1 ))

If  a is > b  then e is set to 1.
Otherwise e doesn't change.

Regardless, programs shouldn't be written with that sort of side effect.  Unless the code was well documented, a maintenance engineer looking for bugs would think he/she found one.  If setting e to 1 only if a > b is the true intent, the code should be written more clearly.

if ( a > b )
{
    e = 1;
    ...
}
0
 
LVL 7

Expert Comment

by:Bill Nolan
ID: 36967366
zoppo: You are correct.  For the example above, I intended:

if (a > b && (e = 1))

...which does NOT make the assignment in all cases as I'd predicted.  However, it's up to the compiler exactly how to handle the precedence of such things, and there occasionally differences.  But it's easy to see why left-to-right evaluation of all assignments and comparisons makes sense by just making another little change:

if (a > b++ && (e = b))

...where "all assignments first" would really start some fun!

hmccurdy:  Indeed, such syntax is generally not advised (except perhaps in certain optimization scenarios).  In fact, I don't particularly like assignments in those kinds of expressions for a variety of uncomfortable reasons!  lol

But the examples were mainly to talk of the compiler mechanics.  Again, I'll find myself testing these things every now and then just to be sure!
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36967459
Slimfinger -- if this about compiler mechanics, fair enough.  I remember one professor warning us that regardless of the standard we shouldn't expect compiler A to act like compiler B (regardless of what the standard might actually say) and then he cited examples.  This was a few years ago and perhaps compilers are better behaved in today's world.

On a really obscure side note -- getting off topic but not too far.  There's a language called APL, which I think is effectively dead, that guaranteed right to left evaluation.  Right to left was required for the language to work as designed (the ability to write one line programs).  It was used mostly by mathematicians.

One classic example of the need to know evaluation order comes from   a = 10 - 7 - 4;
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36967609
Hi again,

sorry, but I disagree with this: However, it's up to the compiler exactly how to handle the precedence of such things, and there occasionally differences

C/C++ standard defines so called sequence-points (see http://en.wikipedia.org/wiki/Sequence_point) where it's granted that the execution of expressions between sequence-points is done from left to right. Beyond some others logical AND and OR operators are such sequence-points, so with an expression like the above one the expression e = 1 must not be evaluated as long as the expression a > b isn't true.

If a compiler interprets this in a different way it hurts the C/C++ standard in a very basic and essential specification. We can be quite sure that there's no well known C/C++ compiler which interprets operator precedence in a none-standard way.

Even in cases like 'a = 10 - 7 - 4' the order of executeion is clearly defined by operator associativity (see http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B). If multiple operators of the same precedence level occur within one expression the order of execution is given by the operator's associativity which is 'left-to-right for operator
-

Open in new window

.

ZOPPO
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36967616
Sorry, made a strange formatting error: I meant given by the operator's associativity which is left-to-right for operator -
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36967648
Zoppo, I agree with your comment about clearly defined related to the subtraction string.  I just provided the example as the classic (IMHO) example of the importance of a standard for such operations.  Oddly enough, I got into an argument with a math professor over this at a party and she conceded.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36967649
And, just for info, there are other cases where order of execution isn't defined in C/C++ specifications - i.e. it's not specified in which order function arguments are evaluated, i.e. take a look at this code:
int x = 5;
int nValue = Add(x, ++x);

Open in new window

With this code it depends on the compiler implementation whether 'Add' is called as 'Add( 5, 6 )' or 'Add( 6, 6 )'. Therefor one should always avoid to use ++ and -- on a variable which occurs more than once within the expression ...
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36967680
Therefor one should always avoid to use ++ and -- on a variable which occurs more than once within the expression ...

Agreed.  
0
 
LVL 7

Expert Comment

by:Bill Nolan
ID: 36967746
The statement "However, it's up to the compiler exactly how to handle the precedence of such things, and there are occasionally differences" in no way implies that there aren't standards.
0
 
LVL 8

Expert Comment

by:eager
ID: 36969527
Operator precedence defines the associativity of the operations, not the order of evaluation.  Operator precedence tells you where the compiler will imply parenthesis.  a = 10 - 7 - 4 is interpreted as a = ((10 - 7) - 4) instead of  a = (10 - (7 - 4)).  Whether you put in parens, or the compiler implies them, the C standard says that the compiler is free to evaluate this expression in ANY order which gives the correct result.  I can think of three equivalent evaluation orders off the top of my head.  

The comment regarding (a > b && e = 1) saying "that sample doesn't compile because the left part of the '=' has to be an lValue but the 'a > b && e' compiles to a 'const' expression" is nonsense.  The expression is not (a > b && e) = 1, but ((a > b) && (e = 1)) as required by operator precedence, since assignment and compare both have higher precedence than &&.
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36969674
Regardless if it's nonsense or not, the GNU C++ compiler (g++) did indeed throw the error.  I could accept that the g++ compiler is broken.  (I won't accept that it didn't throw the error in front of my eyes earlier today.)
0
 
LVL 8

Expert Comment

by:eager
ID: 36969820
Opps, my error. && has higher precedence than =.  
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36969933
Pencils have erasers for a reason.  No harm, no foul.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36977956
So it's no nonsense what I wrote, right?

From operator precedence the if-statement is interpreted as (((a>b)&&e)=1) which cannot be compiled since, as I mentioned, ((a>b)&&e) cannot be a lvalue.

ZOPPO
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36977968
Addition: Operator precedence defines the associativity of the operations, not the order of evaluation

IMO that's not correct: the precedence define the order of evaluation of operators (i.e. as shown in the sample the > is evalulated before the && which is evalulated before =. The associativity defines how operators of the same precedence are grouped in the absence of paranthesis (see http://en.wikipedia.org/wiki/Operator_associativity)

ZOPPO
0
 
LVL 13

Expert Comment

by:Hugh McCurdy
ID: 36979751
Yes, Zoppo, I agree with you on both of your most recent posts.  Operator precedence would have to be involved in the order of operations for the compiler to make any sense of "life."   a * b + c * d had better not start off by adding b+c.
0
 
LVL 8

Expert Comment

by:eager
ID: 36980379
Zoppo & hmcccurdy:  operator precedence and associativity determine how the parse tree is constructed.  Code is generated to evaluate the parse tree. In your  a * b + c * d, the parse tree is (a *b) + (c *d).  There is no computation of (b + c).  

This parse does not require that (a *b) be evaluated before (c * d).  Either subexpression may be evaluated first.  

There seems to be some misunderstanding of the meaning of the word "evaluation".  In compilers, this is when the computation is actually performed, not the abstract meaning of the expression.

The C Standard describes evaluation of expressions.  Unfortunately, it frequently describes what is not permitted under certain circumstances rather than what is.  Here is an example taken from a recent draft of the C Standard.  Note that the last sentence says, in effect, that expressions can be evaluated in any order unless the particular circumstances (trap generated for integer overflow) exist.  There are a number of other places where the C Standard says that ordering is required, such as at a sequence point.  Otherwise, as evaluation order is not constrained, as long as the evaluation is equivalent to the abstract expression.  



EXAMPLE 6 To illustrate the grouping behavior of expressions, in the following fragment

   int a, b;
   /* ... */
   a = a + 32760 + b + 5;

the expression statement behaves exactly the same as

   a = (((a + 32760) + b) + 5);

due to the associativity and precedence of these operators. Thus, the result of the sum (a + 32760) is
next added to b, and that result is then added to 5 which results in the value assigned to a. On a 
machine in which overflows produce an explicit trap and in which the range of values representable by 
an int is [-32768, +32767], the implementation cannot rewrite this expression as

   a = ((a + b) + 32765);

since if the values for a and b were, respectively, -32754 and -15, the sum a + b would produce a trap
while the original expression would not; nor can the expression be rewritten either as 

   a = ((a + 32765) + b);
or
   a = (a + (b + 32765));

since the values for a and b might have been, respectively, 4 and -8 or -17 and 12. However, on a 
machine in which overflow silently generates some value and where positive and negative overflows
cancel, the above expression statement can be rewritten by the implementation in any of the above 
ways because the same result will occur.

Open in new window

0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36984221
I agree that of course 'b + c' in this sample isn't ever computed, because '*' has a higher precedence than '*'

>> Either subexpression may be evaluated first.

But sorry, usually I'm not such pedantic, but I still disagree. As told before the operator's associativity specifies in wich order the statements are put into the parse tree. The associativity of '+' and '*' is 'left-to-right', so it's ensured that some of these samples are calculated as

   (a *b) + (c *d)
   (((a + 32760) + b) + 5)

and not as

   (c *d) + (a *b)
   (a + (32760 + (b + 5)))

In cases where instead of variables function calls or assignments occur in similar statements it's very important in which order the both multiplications are processed since the result of the complete statement can differ depending on the order of evaluation. I.e. if someone has a function 'GetNextCounter' which simply returns a sequence of increasing numbers one by one. Then you can write a similar expression, i.e.:

   x = a * GetNextCounter() + b * GetNextCounter();

Due to associativity (luckily) it's guaranteed that 'a * GetNextCounter()' is calulated before 'b * GetNextCounter()' - without this associaitivity (or, in your words, if Either subexpression may be evaluated first, the result could be one of two possible results, depending how the different compilers implement the filling of the parse tree.

ZOPPO
0
 
LVL 8

Expert Comment

by:eager
ID: 36985113
Zoppo --  A compiler conforming to the ISO C/C++ standard can compute results in the order which is most efficient.  This may not be the same order as written.

If you need to have functions called in a particular order, there needs to be a sequence point between the calls.  In the example you give, different compilers or the same compiler with different optimization can give different results.  

See http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx.  Look for "The compiler is free to evaluate such expressions in any order, if the compiler can guarantee a consistent result."
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36985819
ok, sorry, you're right about the function calls in my above sample. It's not specified in which order these function are called.

I think we're partially talking here about some different cases where in some the associativity can be ignored (as stated in the MSDN article The direction of evaluation does not affect the results of expressions that include more than one multiplication (*), addition (+), or binary-bitwise (& | ^) operator at the same level), in others not (i.e. the same with (-) or (/)).

Somewhere above you wrote Operator precedence tells you where the compiler will imply parenthesis.  a = 10 - 7 - 4 is interpreted as a = (( 10 - 7 ) - 4 ) instead of  a = ( 10 - (7 - 4) ). - that IMO is defined by the operators associativity, not the operator precedence since the two '-' operators have the same precedence. The same is correct if instead one uses functions, i.e. 'a = f() - j() - k()', it even must be evaluated as 'a = ( f() - j() ) - k()', but it's the compilers choice in which order f(), j() and k() are called.

BTW, maybe we should (if we want/need to) continue this discussion in a seperate thread since I don't think it provides further help for Vlearns to get his question answered ...
0
 
LVL 8

Expert Comment

by:eager
ID: 36985923
It isn't limited to function calls; the compiler is free to chose the evaluation order for most subexpressions.  The order of evaluation is only specified in a very limited set of circumstances, such as with || and && operators.

You are correct, I miss-spoke. Operator precedence and associativity each specify where the compiler implies parenthesis.  In the example with multiple subtractions, operator associativity determines this. Neither precedence nor affect evaluation order.  

0
 
LVL 31

Expert Comment

by:Zoppo
ID: 36985981
>> The order of evaluation is only specified in a very limited set of circumstances, such as with || and && operators.
Yes, I agree - as we both told above those are sequence points which must be evaluated in the same order by every compiler ...
0
 

Author Comment

by:Vlearns
ID: 37096224
Please feel free to redistribute the points. I am not an expert enough to distinguish here.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question