Chapter 5 - Language Overview

Chapter 5 - Language Overview

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.

Portability

Non-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 violations

Void 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++ Coding

Functions 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++ errors

Constant 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 Errors

Possibly 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 Coding

Identifier 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

General

Unknown 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 bit
char / 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 integers
0173 / leading zero indicates octal integers (=123 decimal)
0X7B / leading 0X indicates hexadecimal integers (=123 decimal)

Long integer constants:

123L / trailing L indicates long integer
0173L / long integer expressed in octal
0X7BL / long integer expressed in hexadecimal

Unsigned integer constants:

123U / trailing U indicates unsigned integer
0173U / unsigned integer expressed in octal
0X7BU / unsigned integer expressed in hexadecimal

Unsigned long integer constants

123UL / trailing UL indicates both unsigned and long
0173UL / 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 float
1230E-1F / type float in scientific notation

Extended double precision constants:

123.L / trailing L with decimal point or e or E

const1.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