Showing posts with label cstdlib library. Show all posts
Showing posts with label cstdlib library. Show all posts

Friday, 24 February 2012

Keep Console App Window Open in Visual C++


Visual C++ allows you to create a “Win32 Console Application.” It’s like the days before Windows in DOS with the command prompt. If you start a new console app and run it, a window will pop up and close right away. That’s the console window. How do you keep the window form closing so you can see any output? I searched the web and people referred to using system(“pause”). They suggested I add this line of code before the return line in the main function. I tried it and it didn’t work. I received this compile error: C3861: 'system': identifier not found. What they failed to mention was to include the standard library <cstdlib> so the compiler can find the function. Once the include directive was included, the code worked.


Sample Code.

// The standard library includes system function.
#include <cstdlib>

int _tmain(int argc, _TCHAR* argv[])
{


// Pause to keep console window open.
system("pause");

     return 0;
}


The pause argument to the system function will display the message, “Press any key to continue…” and wait until a key is pressed before closing the window.





Wednesday, 22 February 2012

Why The abs Function in C++ Returns A Negative Value

I played around with the abs function in Visual C++ 2010 from the <cstdlib> header file, and in one instance, the function returned a negative value.

Note the parameter for the abs in <cstdlib> is integer and it returns the absolute value.

Here’s the code:

#include <cstdlib>
...
int iVal = -2147483648;
iVal = abs(iVal);

After the call to the abs function, iVal held -2147483648. It was as if nothing had happened. Why? What happened? It has to do with the range for the int data type.

The range of a 32-bit integer is -2,147,483,648 to 2,147,483,647. As you can see, the positive value of the largest negative value is outside the range.

The abs function did work. Here’s a brief explanation of how it worked and why the result is what it is.

A signed integer uses the two’s complement binary number system. That means the left most bit is used as a sign bit (0 for positive and 1 for negative). The remaining bits are used to represent the number.

To simplify things. I’ll use a 4-bit integer. The maximum number of combinations is 2^4 or 16. The largest negative number is 2^(4-1) or 8. The largest positive number is 2^(4-1)-1 or 7. The range is therefore -8 to 7.

In binary we have:

0 1 1 1   equals +7
1 0 0 0   equals -8

So lets take the absolute value of -8 at the bit level.

Start:              1 0 0 0       equals -8
Negate bits:        0 1 1 1       equals  7
Add one             1 0 0 0       equals -8

And so we start with -8 and end up with -8. The same result happens regardless of the size of the signed integer.

Try it with a value that is in range.

Start:             1 1 0 1       equals -3
Negate bits:       0 0 1 0       equals  2
Add one            0 0 1 1       equals  3

Tuesday, 21 February 2012

The Ripped abs Function in C++

I wanted to use the abs function in C++. I checked documentation and found a lack of specifications and seeming contradictions. There were also various versions of functions to get an absolute value (abs, labs, fabs). Instead of trying to make sense of what reference was correct or outdated, I plunged ahead with code to see what would work or what didn’t work. Here’s the results.

Note: I used Visual C++ 2010.
Double Note: The MS documentation on this issue was weak.

Attempt No. 1.

My first attempt was simply to use the abs function on a double variable.

double dVal = -10;
dVal = abs(dVal);

It resulted in a compile error: C3861: 'abs': identifier not found

I knew I needed to include a header file, but I tried it this way to see what would happen.

Attempt No. 2.

What if I added a reference to the standard namespace when calling the abs function?

double dVal = -10;
dVal = std::abs(dVal);

No improvement. This time I got two compiler errors:

C3861: 'abs': identifier not found
C2039: 'abs' : is not a member of 'std'

Attempt No. 3.

Right, time to add a header file, but which one?

#include <cstdlib>
#include <stdlib.h>
#include <cmath>
#include <math.h>.

I saw documentation, text and sample code using one or the other. Instead of continued frustration looking for the answer, I decided I would try each library separately with this code.

#include <cstdlib> | <cmath>
...
double dVal = -10;
dVal = abs(dVal);

The standard library <cstdlib> resulted in a compile error:

C2668: 'abs' : ambiguous call to overloaded function

Running the code with either math library worked fine. The variable dVal becomes 10.000000000000000.

Why the compile error and what header file to include? Part of the confusion lies in the fact the abs function shows up in two different header files.

Here’s what I learnt from the ISO C++ Standard documentation (N3337 2012-01-16). It’s known as C++11—the latest standard of C++, and I should have looked here first.

<math.h> and <stdlib.h> are Standard C library headers. That's the C language, not C++, but since the C++ is a superset of C, the C++ Standard library headers <cmath> <cstdlib> are the same as in C except C++ extends them. (I refer you to paragraph 4 of subclause 26.8 of the ISO C++ Standard.)

The abs function in <cstdlib> takes an integer and returns an integer. If you use the <cmath> library, the function takes a float-point number and returns the same. Both have variations depending on the number of bits used for a particular type.

The <cstdlib> header supports:

int abs (int);
long abs (long);
long long abs (long long);

The long long data type is a 64-bit integer and new to the C++11 standard. This implementation exists in Visual C++ 2010. Microsoft also has it’s own integer types of __intN where N is 8, 16, 32, 64 or 128. __int64 is the same as long long.

The <cmath> header supports:

float abs (float);
double abs (double);
long double abs (long double);


Attempt No. 4.

Focusing on the standard library <cstdlib>, I tested the following code.

#include <cstdlib>
...
int iVal = -10;
iVal = abs(iVal);

The code executes as expected and iVal becomes 10.

But here’s a twist.

#include <cstdlib>
...
iVal = -2147483648;
iVal = abs(iVal);

The value of iVal remains the same. It’s still the exact same negative number. How can that be? To get the answer you have to understand the range of the integer data type. On my computer, int variables are signed 32-bit numbers. The range is -2,147,483,648 to 2,147,483,647. The negative number exceeds the maximum positive number. The abs function worked. It took the negative number, made it positive but since it was larger than the upper limit, it became a negative number. You’ll get the same result if you took the upper limit and added one.


Attempt No. 5.

Focusing on the math library <cmath>, I tested the following code.

#include <cmath>
...
float fVal = -10.123456; // Works.
fVal = abs(fVal);

double dVal = -10.123456; // Works.
dVal = abs(dVal);

The data type long double is the same as double in Visual C++ 2010.

There was no problem using the function.

Attempt No. 6.

The previous code had either the standard library or the math library but not both. What happens when both headers are included? I ran code similar to above and it worked. No compiler errors. No unexpected return values.

Final Thought.

In C, the program has more than one function to determine the absolute value of a number.

abs                 for integers
fabs              for float, double or long double
labs              for long int

Why have variations? Because overloading a function does not happen in C, but it is part of C++. What does that mean? With overloading, the parameters passed to a function can varying depending on their type. In turn, the return value reflects the parameters passed. In C, it needed three different functions to handle the different data types. Not so in C++, yet these C functions  remain because the philosophy of the C++ Standard is to take C and add on to it.