c++ code review




    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)
VlearnsAsked:
Who is Participating?
 
Bill NolanOwner, Lead Technology ProgrammerCommented:
Yes.  It will always evaluate to (ad && etag).
0
 
VlearnsAuthor Commented:
i was afraid that it would evaluate to ad && true

since etag = something is always true

thats not the case right?
0
 
Bill NolanOwner, Lead Technology ProgrammerCommented:
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
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
VlearnsAuthor Commented:
so will the following statement evaluate to true

if (x=0)

0
 
Hugh McCurdyCommented:
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
 
Bill NolanOwner, Lead Technology ProgrammerCommented:
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
 
Bill NolanOwner, Lead Technology ProgrammerCommented:
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
 
ZoppoCommented:
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
 
Hugh McCurdyCommented:

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
 
Bill NolanOwner, Lead Technology ProgrammerCommented:
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
 
Hugh McCurdyCommented:
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
 
ZoppoCommented:
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
 
ZoppoCommented:
Sorry, made a strange formatting error: I meant given by the operator's associativity which is left-to-right for operator -
0
 
Hugh McCurdyCommented:
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
 
ZoppoCommented:
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
 
Hugh McCurdyCommented:
Therefor one should always avoid to use ++ and -- on a variable which occurs more than once within the expression ...

Agreed.  
0
 
Bill NolanOwner, Lead Technology ProgrammerCommented:
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
 
eagerCommented:
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
 
Hugh McCurdyCommented:
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
 
eagerCommented:
Opps, my error. && has higher precedence than =.  
0
 
Hugh McCurdyCommented:
Pencils have erasers for a reason.  No harm, no foul.
0
 
ZoppoCommented:
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
 
ZoppoCommented:
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
 
Hugh McCurdyCommented:
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
 
eagerCommented:
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
 
ZoppoCommented:
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
 
eagerCommented:
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
 
ZoppoCommented:
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
 
eagerCommented:
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
 
ZoppoCommented:
>> 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
 
VlearnsAuthor Commented:
Please feel free to redistribute the points. I am not an expert enough to distinguish here.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.