Note:
11111This lecture notes have been prepared by Michael A. Bodkin (to whom we offer our thanks)
11111and has been slightly modified or re-arranged by Professor V.
Dennis Ritchie at Bell Laboratories took B a step farther by adding data typing (1970) and calling this language C. By the late 1970's a de facto standard developed based on the "The C Programming Language" book by Brian W. Kernighan and Dennis M. Ritchie. This version of C is referred to as K&R C. Due to the variety of hardware platforms that C was ported to. Each implementation would vary from one another.
It became clear to the American National Standards Committee on computers and Information Processing (ANSI) that one standard was needed for C. They began work on the standard during 1983 and completed it in 1990. ANSI cooperated with the International Standards Organization (ISO) to jointly publish the ANSI/ISO 9899: 1990 commonly referred to as ANSI C 1988.
During this time period Bjarne Stroustrup of Bell Labs was developing
a version of C called C++ to support the new Object Oriented (OO) methodology
for solving. This methodology is based on entities in the problem domain
and combining the entity's identity (uniqueness), behavior (functions)
and it's state (characteristics). C++ was made standard in
1998 by ANSI committee.
C++ is an extension of C that supports the Object Oriented (OO) Programming paradigm. (74 reserve words) ANSI C++ 1998 supports the OO paradigm with capabilities of: object creation, inheritance, parametric polymorphism (Templates), and ad hoc polymorphism (Function Overloading, and Type Coercion). C++ extends the OO paradigm by providing for exception handling, name spaces, and Standard Template Library (STL). The STL is a library of container classes (vector, string, set, map, ...) provided for developers use.
The designers of C/C++ have taken the view point that developers
know what they are doing. The benefits of view is there are very fell limitations
on how a developer solves a problem using C++. The drawback is it also
easy to write code that contains memory leaks or can cash the operating
system.
Declarations (type identifier; ):
int i;
// i is an integer
string str; // str is a string
Expressions and Assignments( (identifier | expression) operator (identifier
| expression)[;] ):
i = 0; // the
data named by i now contains the value 0
i = i - 1; // the data named by
i now contains the value -1;
str = "Hello "; // the data named by
str now contains the characters Hello \0;
str = str + "World"; // the data name by str
now contains the character Hello World\0;
Note:
Variables will be called "Identifiers" in the context of this course.
111111
C++ supports fundamental types and user defined types. The fundamental types supported by C++ are:
Boolean Type (bool)
Character Type (char)
Integer Type (int)
Floating point Type (double)
Void Type (void)
Pointer Type (example int*)
Array Type (char [])
Reference Type (double&)
// Discussion tabled to later.
The user defined types are defined using:
Enumeration Declaration (enum)
Structure Declaration (struct)
// Discussion tabled to later.
Class Declaration (class)
// Discussion tabled to later.
Boolean Type can have one of the two values true or false. A Boolean is used to express the results of logical operations. For example:
int i = 0;
int j = 1;
bool result = (i == j); // the data named
by result will contain the value false
// == is equality, = is assignment
j = i;
result = (i==j);
// the data named by result will contain the value true
Character Type can contain one character of the implementation's character set. (A good percentage of the time it is the ACSII Character set). Character Type has two types char and wchar_t. For Example
char ch = 'm';
// the data name by ch will contains the lower case letter m. (Note
C++ is case sensitive.)
// 'm' is refereed to as a literal
wchar_t wch = L'B'; // the data
name by wch contains the wide character upper case b which is part wide
character set usually Unicode.
char and wchar_t types require special functions such as sprintf
to convert from one to another and vice versa. For Example the following
expression is illegal.
ch = wch; // illegal assignment
Both types come in three forms signed char, char, unsigned char which
can be converted from one to another without special functions or casting.
For Example
unsigned char uch = 'u';
char ch = uch;
signed char sch = ch;
ch = sch;
sch = uch;
uch = ch;
uch = sch;
Integer Type has three forms: int, signed int, and unsigned int and come in three sizes: short int, int, and long int. The forms and sizes can be combined and abbreviated. For example signed for signed int, unsigned for unsigned int, short for short int, long for long int. Unlike like the plain char the plain int is signed. Signed int is just an explicit version of int. The compiler will automatically convert between the different signs and sizes, truncating where appropriate. (Note most compilers do not notify the user of this truncation)
long l = -1;
int i = l;
// truncation possible
short s = i;
// truncation possible
s = l;
// truncation possible
i = s;
l = i;
l = s;
Floating Point Type represent floating-point numbers. Just as with integers floating point type has three sizes: float (single-precision), double (double-precisiont), and long double (extedned-precision). The floating point type are implementation dependent. Choosing the right precision for a problem where the choice matters requires significant understanding of floating-point computation. If you don't have that understanding, get advice, take time to learn, or use double and hope for the best.
double small_num = 1.2345E-25;
long double ld = -1.1;
double d = ld; // truncation possible
float f = d;
// truncation possible
f = ld;
// truncation possible
d = f;
ld = d;
ld = f;
Void Type represents nothing and used only to define return types for functions, denote functions with no parameters and to point address locations of undetermined types.
void foo() { ; } // the function foo will return nothing
Pointer Type defines a name that refers to an address location in memory. For example
int i = 0;
int j;
int* pi = &i; // pi is said to point to i the value
in pi is the address location of i.
j = *pi; // j
is assigned the value located in the memory referenced by pi.
// this is called dereferencing the pointer.
A void pointer is a special pointer that can point to any type.
void *vp = pi;
char ch = 'm';
vp = &ch;
vp = &j;
std::cout << "j contains " << *((int*)vp) << endl;
// the following will be printed to standard output.
Array Type defines a name that can hold a given number (size) of elements of that type. Arrays are index from 0 to size - 1. For example
char str[10]; // defines an array
of ten characters
int i_arr[20]; // the data named
by i_arr contains 20 integers
int *p_iarr = i_arr; // the pointer p_iarr contains
the address location of the first integer of i_arr.
int i = i_arr[0]; //
i contains the value index by the first position of the array i_arr
for (int j =0; j < 20; j++) i_arr[j] = 0; // this
command initializes the array i_arr to all zeros
Rules for Identifiers:
EnumerationsExamples of valid names:
- An identifier consists of a sequence of letters and digits.
- An identifier must start with a letter.
- The underscore character _ is considered a letter.
- An identifier cannot be a reserve word
- An identifier must not already be defined within that scope
- The compiler does not impose a limit on the length of an identifier (Some times the a linker or debugger will).
CORE_UTILS Timer CommandFactor __
_WINNT i DisplayMessage01Examples of invalid names:
123 &foo an integer value
$sys no-way dot.notation
enum ATE_INST_STATUS { ATE_GOOD, ATE_BAD, ATE_MISSING
};
ATE_INST_STATUS health = ATE_GOOD;
switch (health)
{
case ATE_GOOD :
// do something
break;
case ATE_BAD :
// do something
break;
case ATE_MISSING :
// do something
break;
default :
// you should never reach this point
}
Enumerations default to starting with zero. For example the statement (ATE_GOOD == 0) will equate to true. You can change that by specifying which integer to start with. For example:
enum MONTHS { JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
It is also legal for you to specify each value. For example:
enum VOLTAGE_RANGE { MIN = -10, MAX = 210 };
enum ARITHMATIC_OPERATORS { PLUS='+', MINUS='-', ASSIGN='=', MULT='*',
POWER='^', DIV='/', MOD='%', LP='(', RP=')' };
Remember the elements of an enumeration set behave as constant integers. The following expression is illegal:
MIN = -210; // This will not compile.
An enumeration is a user-defined type, so user can define their own operations, such as ++ and << for and enumerations.
ostream& operator<<(ostream& in, VOLTAGE_RANGE);
int operator++(VOLTAGE_RANGE& in_range);
+ // plus, both unary and binary root2++; ++root2;
and root2 = 2.1 + 2;
- // minus, both unary and binary root2--;
--root2; and root2 = 2.1 - 2;
* // multiply, root2 = 2.1 * 2;
/ // divide, int i = 7/3; i equals 2.
% // remainder, int i = 7/3; i equals 1.
The comparison operators
== // equal
!= // not equal
< // less than
> // greater than
<= // less than or equal to
>= // greater than or equal to
Resolution Modifiers
class_name::member_name; // scope
resolution modifier
namespace_name::member_name; // scope resolution
modifier
::member_name
// default or no namespace or global scope resolution modifier
Member Selection
object.member_name; // access
a data member or invoke a member function for an object defined off of
the stack
object->member_name; // access a data member
or invoke a member function for an object defined from the Free Store.
Bit wise Operators
expr << expr;
// shift left
expr >> expr; // shift
right
expr & expr;
// AND
expr | expr;
// inclusive OR
expr ^ expr;
// exclusive OR
Logical Operators
(expr1 && expr2) ; // logical
AND returns true or false
(expr1 || expr2)
// logical inclusive OR return true or false
Note: logical operators use short circuit logic so if expr1 of expr1
&& expr2 is false expr2 is not evaluated. If expr1 in expr1 ||
expr2 is not evaluated.
int Square(int value); // This is referred to as a function prototype
void main()
{
int square_of_four = Square(4);
}
The declaration consists of the return type, identifier name, and parameter
list. The return type and parameter list can be comprised of any types.
For this program to run the function Square. For example:
int Square(int value); // This is referred to as a function prototype
void main()
{
int square_of_four = Square(4);
}
int Square(int value) // This is referred to as the function
definition
{
int return_value = value * value;
return return_value;
}
All function parameters are defined off of the stack. To pass in a parameter to be modified your must pass in the address location of that parameter. For example
#include <iostream>
#include <math>
bool SquareRoot(int value, int square_root);
void main()
{
int value = 4;
SquareRoot(value, value);
std::cout << "value = " << value <<
std::endl;
}
bool SquareRoot(int value, int square_root)
{
if (value < 0)
return false;
square_root = sqrt(value);
return true;
}
This program will print out the following string: value = 4
But is we modify SquareRoot:
#include <iostream>
bool SquareRoot(int value, int& square_root);
void main()
{
int value = 4;
SquareRoot(value, value);
std::cout << "value = " << value <<
std::endl;
}
bool SquareRoot(int value, int& square_root)
{
if (value < 0)
return false;
square_root = sqrt(value);
return true;
}
This program will print out the following string: value = 2
In C++ a function is allowed to call it's self for instance take the factorial operation. This is know as recursion and the import thing to remember is to always have a terminating point.
long factorial(long value)
{
if (value > 1)
return ( factorial( value - 1) * value);
else
return 1; // termination point
}
All recursive functions can be converted to a looping construct and
a local variable for efficiently.