Question

How might one craft a good explanation of why the following code is not correct, in that the author is attempting to write C++ code declaratively rather than procedurally?

const double NEWTONS_PER_POUND = 4.448;

int main()
{
   double pounds, newtons;
   pounds = newtons/NEWTONS_PER_POUND; /* pounds equals 'unassigned variable'/4.448 */
   newtons = 10.0;
   cout << pounds << endl;             /* a big number, not 10.0/4.448 */
   return 0;
}

The author expected cout to display a proper calculation, but instead gets a "crazy number."

I would explain this as "C++ is procedural, and therefore at the time of the declaration

pounds = newtons/NEWTONS_PER_POUND;

newtons has not been assigned a value.

Any better suggestions? Or an explanation why C++ isn't "smart" enough to carry out the behavior the user mistakenly expected?

Was it helpful?

Solution

Tell the author that

pounds = newtons/NEWTONS_PER_POUND;

commands the CPU to

  • take the value at the address referred to as "newtons"
  • take the value at the address referred to as "NEWTONS_PER_POUND"
  • divide them
  • store the result at the address referred to as "pounds"

what he is looking for is most probably a function in imperative terms:

double newtons_to_pounds(double newtons) {
  return newtons/NEWTONS_PER_POUND;
}

...

newtons = 10.0;
cout << newtons_to_pounds(newtons) << endl;    /* a big number, not 10.0/4.448 */
return 0;

OTHER TIPS

C++ is an imperative programming language not an equation solver.

C++ executes statements in the order that you write them. C++ does not initialize variables unless it is told to. C++ allows you to use a variable whose value has not been initialized, but when you do this the result is unspecified. Unspecified means than anything can happen, including bad things like producing "crazy numbers".

Here's the detailed explanation:

double pounds, newtons;
pounds = newtons/NEWTONS_PER_POUND;
newtons = 10.0;

The first statement declares two variables without initializing them. At this point, their values are unspecified.

The second statement reads the value of newtons (which could be anything) and divides it by NEWTONS_PER_POUND. The result (which could be anything) is assigned to pounds.

The third statement initializes newtons, but it is too late to affect the calculation we just performed.

Well that shouldn’t be too hard to explain, regardless of the students’ background: just thell them that C++ evaluates programs one step at a time, statement after statement (notwithstanding compiler artifacts such as reordering …).

There’s absolutely nothing special to C++’ way of handling this, nor is it even limited to computer programming – rather, it’s an everyday way of dealing with an ordered list of instructions.

It's not lazy evaluating newtons

As such the calculation is performed at the time of declaration, not at the time of request. He's after functional code, not what C++ will do.

If the person is not overly technical you could try:

"The statements in this C++ program are like the steps required to make a cake. You must perform the steps one by one and they must be to be performed in a certain order for it to be a success."

Explain that pounds is assigned a value on the line with the assignment operator:

pounds = newtons/NEWTONS_PER_POUND;

If this were not the case, but that pounds was evaluated when it was used (as with the cout statement), then if the value of newtons changed, then the value of pounds would change as well. Since pounds is not any type of pointer, but is a simple integer, this is not possible.

What about stepping through the code in a debugger?

IME there's nothing like this to understand the execution of a program written in a procedural language (i.e., modeled on how the CPU actually executes code).

You are trying to get the listener to undergo a paradigm shift - to change his/her entire approach to comprehending this code.

"pounds" is just a number. It's got no concept of how its created. You tell "pounds" how it's created, it won't remember. It will just remember what it is, not how it is created.

It may seem a bit strange to anthropomorphise a block of memory. :-)

Take a slightly more complex example where a variable like newtons is reused and assigned values more than once. For instance:

double pounds, newtons;

newtons = 10.0;
pounds = newtons/NEWTONS_PER_POUND;
cout << pounds << endl;

newtons = 15.0;
pounds = newtons/NEWTONS_PER_POUND;
cout << pounds << endl;

return 0;

Show him both the code and the output. Then ask him to explain how and why the program produces a different number for each line. I'd think that should help push him in the direction of viewing the program as a procedure that runs from top to bottom.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top