Part 5
Language Overview
Compiler settings
Tutorial examples of C++ programs.
Examples of variables, constants, and, arithmetic.
Copyright © 1992-1997 Thomas P. Sturm
Error Checking in Turbo C++ and Borland C++
1. Select options from main menu
2. Select project from options menu
3. Double click on messages (if preceded by a +)
3.a. This allows viewing the 8 message categories
4. Click on each message category in turn
4.a. This allows viewing of 3 to 13 check boxes
5. Click on each unchecked item to check it
6. Click on OK after completion of 8 message categories
OR
1. Select options from main menu
2. Select project from options menu
3. Click on messages
4. Click on ALL diamond to enable all messages (does not change selected messages in each category - messages not checked in each category will be disabled when the SELECTED diamond is clicked)
PROGRAM ERROR CHECKING
Turbo C++ and Borland C++ use compiler switches or options to control the extent of error checking.
The sequence on the opposing page will make the Turbo C++ and Borland C++ compilers as error sensitive as possible.
Not all programming errors, of course, can be found during compile time. Be sure to watch for compiler, linking, and execution errors.
Thus, you should do separate compilation, linking, and running (Alt-F9, followed by F9, or Alt-F9 followed by Ctrl-F9).
To enable checking for stack overflow:
1. Select options from main menu
2. Select project from options menu
3. Click on compiler until compiler options expanded
4. Click on debugging until debugging options expanded
4. Click on TEST STACK OVERFLOW box until box is checked.
Be sure to watch for messages at the end of execution. If you have "left something behind" that is discovered at the end of execution, this is a very serious error and must be fixed.
Be particularly wary of any program that gives a “null pointer assignment” error message at the end of execution or warns of possible “memory leakage.”
Turbo C++ and Borland C++ Error Options
The Turbo C++ and Borland C++ compilers have over 50 independent error checking options that can be enabled or disabled. Borland C++ 4.0 for Windows has 56 options divided into 8 categories.
PortabilityNon-portable pointer conversion
Non-portable pointer comparison
Constant out of range in comparison
Constant is long
Conversion may lose significant digits
Mixing pointers to different ‘char’ types
ANSI violationsVoid functions may not return a value
Both return and return with a value used
Suspicious pointer conversion
Undefined structure structure
Redefinition of macro is not identical
Hexadecimal value contains more than three digits
Bit fields must be signed or unsigned int
Identifier is declared as both external and static
Declare type prior to use in prototype
Division by zero
Initializing identifier with identifier
Initialization is only partially bracketed
Non-ANSI keyword used: word
Obsolete C++Base initialization without a class name is now obsolete
Style of function definition is now obsolete
Overloaded prefix operator used as a postfix operator
Inefficient C++ CodingFunctions containing identifier are not expanded inline
Temporary used to initialize identifier
Temporary used for parameter in call to identifier
Borland C++ 4.0 for Windows Error Options (Continued)
Potential C++ errorsConstant member identifier is not initialized
Assigning type to enumeration
Function1 hides virtual function function2
Non-const function function called for const object
Base class base1 is also a base class of base2
Array size for ‘delete’ ignored
Use qualified name to access nested type type
Handler for xxx is hidden by previous handler for yyy
Conversion to type will fail for members of virtual base base
Maximum precision used for member pointer type type
Use ‘> >‘ for nested templates instead of ‘>‘
Non-volatile function function called for volatile object
Potential ErrorsPossibly incorrect assignment
Possible use of identifier before definition
No declaration for function function
Call to function with no prototype
Function should return a value
Ambiguous operators need parentheses
Condition is always true/false
Inefficient CodingIdentifier is assigned a value that is never used
Parameter identifier is never used
Identifier is declared but never used
Structure passed by value
Unreachable code
Code has no effect
GeneralUnknown assembler instruction
Ill-formed pragma
Array variable variable is near
Superfluous & with function
Identifier is obsolete
Cannot create precompiled header: header
C++ COMMENT STYLES
/* Style used in these notes, comment delimiters are tight against text */
/* Open comment / close comment style in which the close comment always starts a new line - takes extra space, but a bit easier to find
*/
/*
Extra whitespace style comment in which the open comment and close comment are both on separate lines - still more space, still easier to find
*/
/**********************************************
* Box style - you can’t miss these, but takes *
* lots of space, and VERY hard to maintain *
**********************************************/
// End-of-line comment - only one style
// Use these almost exclusively in C++
// Except for very long comments
// Or comments at the beginning of a file
GETTING FANCY WITH COMMENTS
These notes show only one style of comments when using the comment of the form /* ... */. The style shown has the /* immediately precede the comment text, and the */ immediately follow the comment text. Other possible styles are shown on the opposite page
The end-of-line comment, which begins with // and ends with the end of the current line, should probably be used for all comments except perhaps those at the beginning of a file. The reason for this is that comments of the form /* ... */ do not nest. This means you cannot comment out code that contains these kinds of comments. You will want to comment out code when testing or making changes. You can comment out code using comments of the form /* ... */ if the comments in the code begin with // and end with the end of the current line.
Reserved Names in C++
Language OverviewPart 5, Page 1
asm
auto
bool
break
case
catch
cdecl †
char
class
const
const_cast
continue
default
delete
do
double
dynamic_cast
else
entry
enum
explicit
extern
false
far †
float
for
fortran
friend
goto
handle
huge †
if
inline
int
interrupt †
long
mutable
namespace
near †
new
noalias
operator
overload
pascal †
private
protected
public
register
reinterpret_cast
return
short
signed
sizeof
static
static_cast
struct
switch
template
this
throw
true
try
typedef
typeid
typename
union
unsigned
using
virtual
void
volatile
wchar_t
while
Language OverviewPart 5, Page 1
† indicates names reserved in the Borland implementations
...and names beginning with an underscore (these names are reserved by the implementation, e.g. 75 in Borland C++ 4.0)
VARIABLE NAMES
Variable names must start with a letter or underscore and continue with letters, digits, or underscores. Upper and lower case characters are distinct. Variable names starting with a single underscore are generally reserved for the compiler and implementation details, and variable names starting with more than one underscore are generally reserved for the linker.
By convention, variable names are entirely in lower case (or multi-word variable names may have upper case letters beginning each new word), except symbolic names which are entirely in upper case. Typedef and class names are in mixed case.
C++ imposes no limitation on variable length, so, in theory, variable names are of unlimited length and kept distinct. However, C compilers had the first 31 characters of the variable name significant. (If more were used, variations occurring after the first 31 identical characters caused unpredictable results.) Many C++ compilers impose practical limits. For maximum compatibility, keep the length of variable names under 32 characters.
External names (function names and external variable names) may be restricted in length because of implementation details (typically imposed by linkers and loaders). Some restrict these names to as short as 5 characters, but generally you should assume you can use up to 13 character names with reasonable portability.
C++ is a keyword language, so language keywords may not be used as variable names.
External names should not duplicate the names of desired external variable names, library functions, or names that are special to the linker. Avoid names like delete, end, getchar, cin, cout, ios, printf, storage, system, or any function names found in the documentation.
In summary, C++ is a case-sensitive, reserved-word, free-format, block-structured, third generation, object-oriented programming language with no input/output statements.
size.cpp
/* SIZE.CPP: Find out how much storage (in bytes)
is allocated for variables of each type */
#include <iostream.h>
main ()
{
int a, b, c, d, e, f, g, h;
double *i;
a = sizeof (short);
cout < "short integers occupy " < a < " bytes\n";
b = sizeof (int);
cout < " integers occupy " < b < " bytes\n";
c = sizeof (long);
cout < " long integers occupy " < c < " bytes\n";
d = sizeof (char);
cout < " characters occupy " < d < " bytes\n";
e = sizeof (float);
cout < "floating point occupy " < e < " bytes\n";
f = sizeof (double);
cout < "double precis. occupy " < f < " bytes\n";
g = sizeof ('X');
cout < "a char const occupies " < g < " bytes\n";
h = sizeof (i);
cout < " pointers occupy " < h < " bytes\n";
return 0;
}
Built-In Objects
The code on the opposite page shows how to obtain the number of bytes reserved by the built-in objects. Each byte is presumed to be at least 8 bits long.
The sizeof operator works for built-in data types and objects, user-defined classes and objects, and aggregates of objects
The minimum ranges of the various data types are:
bool / 1 bitchar / 8 bits
signed char / ±127
unsigned char / 255
wchar_t / 16 bits
short int / ±32,767
unsigned short int / 65,535
int / ±32,767
unsigned int / 65,535
long int / ±2,147,483,647
unsigned long int / 4,294,967,295
float / 6 decimal digits, 1E±37 range
double / 10 decimal digits, 1E±37 range
long double / 10 decimal digits, 1E±37 range
ESCAPE SEQUENCES IN C++
sequence / meaning\a / alert (bell)
\b / backspace
\f / formfeed
\n / newline
\r / carriage return
\t / horizontal tab
\v / vertical tab
\\ / backslash
\? / question mark
\’ / single quote
\” / double quote
\0 / null
\0ooo / octal number
\xhh / hexadecimal number
Outline for a Properly Constructed Program
Introductory comments
- Name of file containing the code
- Date written
- Author
- General purpose of the code
#include statements
- System libraries #include < ...
- User libraries #include " ... "
#define statements
- Symbolic constants
- Macros
Structure, union, and typedef declarations
Function declarations
Global variables
main
Other functions
CHARACTER CONSTANTS
'A' to 'Z' / Capital letters'a' to 'z' / Lower case letters
'0' to '9' / Digits
'!', '#', etc. / Special printable characters
'\a' / Alert (bell) character
'\b' / Backspace
'\f' / Form feed (page eject, top of form)
'\n' / Newline (linefeed)
'\r' / Carriage return
'\t' / Tab
'\v' / Vertical tab
'\\' / Backslash
'\?' / Question mark
'\'' / Single quote
'\"' / Double quote
'\0' / Null (by convention, a string terminator)
'\014' / The character whose octal code is 014 (in ASCII, a form feed)
NUMERIC CONSTANTS
Integer constants:
123 / decimal integers0173 / leading zero indicates octal integers (=123 decimal)
0X7B / leading 0X indicates hexadecimal integers (=123 decimal)
Long integer constants:
123L / trailing L indicates long integer0173L / long integer expressed in octal
0X7BL / long integer expressed in hexadecimal
Unsigned integer constants:
123U / trailing U indicates unsigned integer0173U / unsigned integer expressed in octal
0X7BU / unsigned integer expressed in hexadecimal
Unsigned long integer constants
123UL / trailing UL indicates both unsigned and long0173UL / unsigned, long, in octal
0X7BUL / unsigned, long, in hexadecimal
Double precision constants:
123. / decimal point or e or E must appear..123E3 / significant digits before or after decimal point must appear
12300e-2 / number may be in standard or scientific notation
Floating point (single precision) constants:
123.0F / trailing F indicates float1230E-1F / type float in scientific notation
Extended double precision constants:
123.L / trailing L with decimal point or e or Econst1.cpp
// const1.cpp - show use of constants
#include <iostream.h>
main()
{
const int maxSize = 100;
int size;
size = maxSize - 1;
cout < "Size = " < size <
", Max = " < maxSize < "\n";
return 0;
}
const2.cpp
// const2.cpp - show abuse of constants
#include <iostream.h>
main()
{
const int maxLen = 100; // OK so far
const int maxWidth;
// but you can't do anything with it
int len;
maxWidth = 40; // compiler error
len = maxLen--; // compiler error
return 0;
}
const IS A PROMISE
- const is a promise to the compiler that a “variable name” is, in fact, just a symbolic representation of a constant.
- A const object must be given a value at the time it is defined - the value that it is the symbolic representation for
- A const object can be used anywhere that a constant is required
- A const object cannot be changed. If you try to get tricky by using pointers and other mechanisms to bypass the const promise, the compiler with just make a copy of the constant and change the copy.
- const1.cpp will run, while const2.cpp will not.
math.cpp
/* MATH.CPP: Program to illustrate associative problems
with addition */
#include <iostream.h>
main()
{
double a, b, c, x, y, z;
x = 1.2e+30;
y = -1.2e+30;
z = 2.3;
a = x + y; // should be zero
b = x + z; // 1.2e+30 to 28 sig. digits
c = y + z; // -1.2e+30 to 28 sig. digits
cout < (a+z) < ' ' < (b+y) < ' ' < (c+x) <endl;
cout < (x+y+z) < ' ' < (x+z+y) < ' '
< (y+z+x) < endl; // no guarantees
cout < ((x+y)+z) < ' ' < (x+(y+z)) < ' '
< ((x+z)+y) < endl; // OK
return 0;
}
ARITHMETIC OPERATIONS
+Adds two numbers, but A + B means add A to B or add B to A. So A + B + C may add A and B first, or B and C first. Use parentheses to force grouping.
-Subtracts two numbers.
*Multiplies two numbers. As in addition, A * B means multiply A by B or multiply B by A.
/Divides two numbers. If both are of type int, it performs an integer division, truncating the result.
%Computes the remainder from integer division. This operator doesn't apply to float or double types.
unary -Changes the sign of the operand following it.
A “variable” declared const can be used to specify array size and anywhere else a compile-time constant is required. A const object cannot be modified by any executable statement or module. If a module attempts to modify a const object, a copy may be made and the copy modified (or the program could just not compile without errors)
C++ allows variables to be defined in many more places within the code (closer to the point of usage), not just at the heads of blocks. This is particularly useful for "meaningless" loop counters.
Type Conversion Examples
Conversions are done across assignment. Note that:
int i;
char c;
i = c;
c = i;
is guaranteed not to change valid characters.
Values are widened, rounded, or truncated as necessary.
int i;
double x;
i = x;
truncates the value stored in x (2.9 becomes 2, -3.6 generally becomes -3, but is permitted to “truncate” to -4).
float a;
double x;
a = x;
rounds the value of x to the nearest value that can be stored in a.
long w;
int i;
i = w;
drops off the high-order bits in the representation of w.
TYPE CONVERSION
Conversions need to be done whenever
- a set of actual parameters doesn’t exactly match a function prototype
- arithmetic is done on two operands of different types
- assignment is done from one type to another
- initialization is done with a type different than the object initialized
Expressions that don't make sense are disallowed.
e.g. floating point subscripts
Expressions that might lose information draw warnings.
Conversions that widen one operand to make both operands of the same type are done automatically.
Characters are converted to integers using a machine-dependent conversion routine. (Usually, they just allow the bit pattern representing the character to be interpreted as a binary number.) Standard characters are guaranteed to produce positive integers, but arbitrary patterns stored in character variables may not yield positive integers.
The following rules apply to type conversion in simple cases (no unsigned operands).
If either operand is long double, convert the other to long double.
Otherwise, if either operand is double, convert the other to double.
Otherwise, if either operand is float, convert the other to float.
Otherwise, if either operand is long int, convert the other to long int.
Otherwise, (must have char, short int, enum, and/or int), convert to int.
plusplus.cpp
// PLUSPLUS.CPP: Test ++ and -- operators
#include <iostream.h>
main()
{
int a = 10, b = 20, c = 30, d = 40, e = 50, f = 60,
g = 70, h = 80, i = 100, j = 100, k, l;
a++;
++b;
c--;
--d;
cout < "a=" < a < " b=" < b;
cout < " c=" < c < " d=" < d < endl;
cout < e++ < " " < ++f;
cout < " " < g-- < " " < --h < endl;
k = i++;
l = ++j;
cout < "i=" < i < " j=" < j;
cout < " k=" < k < " l=" < l < endl;
return 0;
}
INCREMENT AND DECREMENT OPERATORS
The increment operator ++ adds one to its operand. The decrement operator -- subtracts one from its operand.
There are two ways to use the operator, prefix (before the operand) and postfix (after the operand). The prefix operator increments the operand before using it. The postfix operator increments the operand after using it.
Example:
int x, n;
n = 5;
x = n++;
sets x to 5, but
int x, n;
n = 5;
x = ++n;
sets x to 6. In both cases, n becomes 6.
Increment and decrement apply only to variables, not expressions.
assign.cpp
/* ASSIGN.CPP: Program to illustrate the assignment
operator */
#include <iostream.h>
main()
{
double x = 2.0, y = 3.0, z = 8.0;
x += 5.0;
y *= 12.0;
z /= 2.0;
cout < "x = " < x < " y = " < y;
cout < " z = " < z < endl;
return 0;
}
RESULTS OF ASSIGN.CPP
x = / y = / z =ASSIGNMENT OPERATORS
Expressions such as
i = i + 2;
in which the left hand side is repeated on the right can be written in the compressed form
i += 2;
using the assignment operator += .
The following binary operators have a corresponding assignment operator op=, where op is one of the following:
+-*/%^|
If e1 and e2 are expressions and op is one of the above, then
e1 op= e2
is equivalent to
e1 = e1 op e2
For example,
x /= 2
is equivalent to
x = x/2
PRECEDENCE CHART OF C++ OPERATORS
OPERATOR / NAME / OVER / GROUPING() / function call / yes / left-to-right
[] / array element / yes
. / structure, union member / no
-> / structure, union pointer / yes
:: / scope access / no
! / logical not / yes / right-to-left
~ / one's complement / yes
+ / (unary) plus / yes
- / (unary) minus / yes
++ / increment / yes
-- / decrement / yes
address / yes
* / indirection / yes
(type) / type cast / yes
sizeof / size in bytes / yes
new / dynamic storage allocation / yes
delete / dynamic storage deallocation / yes
.* / deref pointer to class member / no / left-to-right
->* / deref ptr to ptr to class mem / yes
* / multiplication / yes / left-to-right
/ / division / yes
% / remainder / yes
+ / addition / yes / left-to-right
- / subtraction / yes
shift left / yes / left-to-right
shift right / yes
less than / yes / left-to-right
<= / less than or equal / yes
greater than / yes
>= / greater than or equal / yes
== / equal / yes / left-to-right
!= / not equal / yes
bitwise and / yes / left-to-right
^ / bitwise exclusive or / yes / left-to-right
| / bitwise or / yes / left-to-right
logical and / yes / left-to-right
|| / logical or / yes / left-to-right
?: / conditional / no / right-to-left
= / assignment operator / yes / right-to-left
+= / assignment replace add / yes
-= / assignment replace subtract / yes
*= / assignment replace multiply / yes
/= / assignment replace divide / yes
%= / assignment replace remainder / yes
<= / assignment replace shift left / yes
>= / assignment replace shift right / yes
&= / assignment replace and / yes
^= / assignment replace exclusive or / yes
|= / assignment replace or / yes
, / comma / yes / left-to-right
STATEMENTS AND BLOCKS