Re: Could you please explain this code segment

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 17 Dec 2009, Bill McEnaney wrote:


Maybe it's too meaningful, i.e., too ambiguous.  Were it literally
meaningless, would it be compilable and executable?

It's not possible to detect all cases undefined behavior at compile time, although GCC will warn you about many of them with -Wall:

 $ cat test.cpp
#include "stdio.h"

int
main()
{
  int a = 0;
  printf("%d %d", a++, a++);
  return 0;
}

 $ gcc -Wall test.cpp
test.cpp: In function ʽint main()ʼ:
test.cpp:7: warning: operation on ʽaʼ may be undefined

As I understand it, the reason the C standard leaves room for undefined behavior is that it gives compiler writers freedom to optimize code in ways which would be impossible if everything was precisely defined. The standard committee could easily have defined every operator and comma as a sequence point, but then there would be no way to tell the compiler, "This code will behave the same way no matter what order the subexpressions are evaluated, so do whatever is most efficient." When the order of evaluation does matter, you can divide the code into separate, semicolon-delimited statements and get exactly what you want. If you lie to the compiler by saying order doesn't matter when it does, you might get what you want or you might get garbage.

C is more than a cross-platform assembly language where every operation maps directly to a series of machine instructions. If it was, writing a compiler would be easy - and writing efficient, portable application code would be much harder.

By the way, here it is from the horse's mouth [1]:

  3.4.3
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
  for which this International Standard imposes no requirements
NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
2
results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or
  execution (with the issuance of a diagnostic message).
EXAMPLE An example of undefined behavior is the behavior on integer overflow.
3


[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf



If multiple increment and decrement operators (++ --) are used in the
same statement, it's undefined which ones happen first.  Therefore:

int a = 0;
cout << a++ << a++ << endl;

could produce 0 1 or it could produce 1 0.  It would be very bad to
rely on any specific compiler behavior as this would be extremely
fragile code.  The only guarantee is that the variable is modified
before or after the usage.

Because it's undefined what should happen, it could be considered
meaningless.

  Brian

On Thu, Dec 17, 2009 at 11:52 AM, Bill McEnaney <bill@xxxxxxxxxxxx> wrote:
Where's the meaningless(?) code?

On Thu, 2009-12-17 at 10:40 -0700, Joel Dice wrote:
On Thu, 17 Dec 2009, Bob Plantz wrote:



I have seen many, many examples, both in industry and in academia,
where
programmers write tricky code claiming it is more efficient. I
claim (a)
efficiency is seldom an issue, and (b) looking at the generated
assembly
language almost always shows it is not more efficient.

I believe that the best code is that which (a) correctly solves the
problem, and (b) is the most simple-minded in appearance.

Perhaps, but the code in question here is not merely obscure - it's
simply
meaningless.  I think it's a mistake to put such code in the same
category
as e.g. an affine transform implemented in inline assembly which has
well-defined meaning.  The latter may pose a challenge for a
maintenance
programmer, but at least it will yield to persistence.  In contrast,
undefined code is no better than a "todo" comment - you're only
option is
to replace it completely with something well-defined based on the
documentation and/or context.


I agree that there are situations where obscure code is the best,
perhaps the only, way to solve the problem. For example, in 1984 I
had a
consulting job where one of my assignments was to write a logarithm
function for an embedded MC68000 environment. The only way I could get
the required speed and accuracy was to use double-precision integer
arithmetic. I wrote it in assembly language and used several "magic
numbers" to keep intermediate values in range while maximizing
arithmetic significance. My comments took more space in the listing
than
the actual code. To their credit, the programming team asked for even
more documentation during my walk-through of my code.

These situations are uncommon -- and lots of fun to solve!

The most common uses of obscure code that I've seen are programmers
showing off their "understanding" of the language being used. I believe
that a good programmer does not ask what his/her code does, but rather
explains it -- either through simple, easy-to-read code, or with
thorough commenting. I use the term "good" to mean relative to the
programmer's skill level.

--Bob




________________________________________________________________
Please visit a saintly hero:
http://www.jakemoore.org




________________________________________________________________
Please visit a saintly hero:
http://www.jakemoore.org

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux