Basic Building Blocks of C++
Structure of a C++ Program
- Sequence of statements, typically grouped into functions
- For a C++ executable, exactly one function called main()
- Can consist of multiple files and typically use libraries
- Statement -- smallest complete executable unit of a program
- Declaration statement
- Execution statement
- Compound statement -- any set of statements enclosed in set
braces { } (often called a block
- Library
- usually pre-compiled code available to the programmer to
perform common tasks
- Many libraries come with compilers. Some standard for all compilers,
and some may be system specific
- location of pre-compiled implementation code known to compiler
- library is defined for the program via a header file (the
interface)
- Use the #include directive to make a library part of a
program (satisfies declare-before-use rule)
Atomic Data Types
Atomic data types are the built-in types defined by the C++ language
- The types
-
Integer types -- char, short, int, long
- Can be signed or unsigned
-
Floating Point types -- float, double, long double
-
Special type -- bool (has values true and false)
- Sizes
- Sizes for these types are implementation dependent
- numerical types above listed in smallest to largest order
- can use built-in sizeof() function to find out sizes of
types or variables for a system
- For most computers today: char typically 1 byte;
int typically 4 bytes
This program will print the number
of bytes used by each type - sizes may vary from system to system
Variables
Every variable has a:
- Name -- chosen by the programmer (aka identifier)
- Type -- specified in the declaration of the variable
- Size -- determined by the type
- Value -- the data stored in the variable's memory location
- Address -- the location in memory where the value is stored
When a program is compiled, a symbol table is created, mapping
each variable name to its type, size, and address
Naming Variables
- Identifiers can consist of letters, digits, and underscores
- Must start with a non-digit (better to not start with underscore)
- Identifiers are case sensitive
- Reserved words cannot be used as identifiers
A list of reserved keywords in C and C++ can be found in Deitel, pg. 75.
Declaring Variables
Declaration format: typeName variableName;
int x;
float y;
int a, b, c; // can also list several variables in one declaration
// statement, separated by commas
int a=0, b=0, c; // can also initialize atomic variables in
// declaration statements
Constant declaration format: const typename variablename =
value;
(must initialize in same statement)
const double PI = 3.14159;
Declaration Examples
Literals
-
integer literal -- an actual integer number written in code (4,
-10, 18)
-
float literal -- an actual decimal number written in code (4.5,
-12.9, 5.0) -- Note: these are interpreted as type double by
most C++ compilers
-
character literal -- a character in single quotes: ('F', 'a',
'\n')
-
string literal -- a string in double quotes: ("Hello", "Bye",
"Wow!\n")
Comments
Operators
-
Operators are functions! They just have a more familiar notation (often
known as infix notation. Get used to thinking of operators as
functions -- we will eventually be defining our own operators.
int x, y, z;
...
z = x + y; // infix notation for + operator
z = operator+(x,y); // alternate (valid) notation -- called like a function
- arity -- how many operands
- unary operator -- has one operand
- binary operator -- has two operands
- ternary operator -- has three operands
- Only ternary operator is the "conditional expression" operator
(expr ? expr : expr). The rest are unary or binary
Arithmetic Operators
Name |
Symbol |
Arity |
Usage |
Add |
+ |
binary |
x + y |
Subtract |
- |
binary |
x - y |
Multiply |
* |
binary |
x * y |
Divide |
/ |
binary |
x / y |
Modulo |
% |
binary |
x % y |
Minus |
- |
unary |
-x |
Operator precedence
- Arithmetic has usual precedence
- parentheses
- Unary minus
- *, /, and %
- + and -
- operators on same level associate left to right
- 18 different levels of operator precedence
- When in doubt, can always use parentheses
Increment and Decrement
++x; // pre-increment (returns reference to new x)
x++; // post-increment (returns value of old x)
// shortcuts for x = x + 1
--x; // pre-decrement
x--; // post-decrement
// shortcuts for x = x - 1
Pre-increment: incrementing is done before the
value of x is used in the rest of the expression
Post-increment: incrementing is done after the
value of x is used in the rest of the expression
Note - this only matters if the variable is actually used in
another expression. These two statements by themselves have the
same effect:
x++;
++x;
Examples
int x = 5, count = 7;
result = x * ++count; // result = 40, count = 8
int x = 5, count = 7;
result = x * count++; // result = 35, count = 8
Assignment Operator
- Value on the right side (r-value) is assigned to the location
(variable) on the left side (l-value)
- R-value -- any expression that evaluates to a single value
(name comes from "right" side of assignment operator)
- L-value -- A storage location! (not any old
expression).
A variable or a reference to a location. (name comes from "left" side of
assignment operator
- The assignment operator returns a reference to the l-value
- Examples
x = 5;
y = 10.3;
z = x + y; // right side can be an expression
a + 3 = b; // ILLEGAL! Left side must be a storage location
- Associates right-to-left
x = y = z = 5; // z = 5 evaluated first, returns z
- Be careful to not confuse assignment = with comparison
==
Other Special short-cut assignment operators
v += e; means v = v + e;
v -= e; means v = v - e;
v *= e; means v = v * e;
v /= e; means v = v / e;
v %= e; means v = v % e;
Automatic Type Conversions
- Typically, matching types are expected in expressions
- If types don't match, ambiguity must be resolved
- There are some legal automatic conversions bewteen built-in
types. Rules can be created for doing automatic type conversions between
user-defined types, too
- For atomic data types, can go from "smaller" to "larger" types.
General rule of thumb: Allowed if no chance for partial data loss
char -> short -> int -> long -> float -> double -> long double
- Should avoid mixing unsigned and signed types, if possible
- Examples:
int x, y;
double a, b;
char c;
unsigned int u;
a = x; // legal.
c = x; // illegal. trying to stuff int into char (usually 1 byte)
x = a; // illegal. Might lose decimal point data.
x = c; // legal
u = x; // dangerous (possibly no warning)
b = a + y; // result of double + int is a double
b = a / y; // floating point division (at least one operand a float type)
Explicit type conversions (casting)
- Older C-style cast operations look like:
c = (char)y; // cast a copy of the value of y as a char, and assign to c
x = (int)b; // cast a copy of the value of b as an int, and assign to x
- Better to use newer C++ cast operators. For casting between
variables, use static_cast
c = static_cast<char>(y);
x = static_cast<int>(b);
Input and Output with streams in C++:
In C, we use functions found in stdio.h -- printf, scanf
In C++ we use different standard methods of i/o -- streams.
cout -- output stream object, of type ostream
cin -- input stream object, of type istream
To use these streams, we need to include a library called
iostream into our programs
#include <iostream.h> // older style
or
#include <iostream> // newer C++ style
cout is most frequently used with the insertion operator <<
cout << "Hello World";
cout << 'a';
cout << x << y << z;
cin is most frequently used with the extraction operator >>
cin >> x;
cin >> a >> b >> c;
Note: You cannot use literals on the right side of the extraction
operator. The cin statement should read data IN to a variable location.
The right side of the >> operator must specify a storage location.
Sample programs:
Note: In the above Hello, World examples, you will see a few
differences, illustrating differences between the older and newer C++
styles. C++ was officially standardized in 1998, so some older code will
not reflect some of the newer features. A few worth noting:
"int main()" vs "void main()"
the newer style is to use int as the return type on the main
function, which allows one program to receive a message of
success or failure (with a given error code) from another calling program.
This is commonly used, for example, in operating systems
processes. Note also that the version with "int main()" has a return
statement at the end, returning an integer value. In this context,
typically 0 is used to report success, and a variety of negative values
are used to report errors.
In the #include statement, <iostream.h> vs. <iostream>
the older style of #include statements uses the exact name of the
header
file (with the .h extension). The newer style of #includes uses a
different naming scheme, which is also extended to the older C libraries.
This is described in Deitel starting on page 180.
The "using" statements
there is a newer feature in the C++
language
called namespaces, and the "using" statement helps take advantage
of this. In these examples, the "using" statements are there to identify
that the "cout" and "cin" words that we are using come from the "standard"
namespace. Some older compilers (like Borland C++ 5.0) do not recognize
or understand "using" statements and namespaces, as they pre-date the 1998
standardization.
While some compilers do not recognize some newer features, most newer
compilers can handle the older styles, as well. For example, the g++
compiler will understand all of the above examples without any problem.
Scope:
The scope of a variable is the portion of the code where a variable is
valid
A global variable is declared outside of any compound blocks and is
usable anywhere in the file from its point of declaration
A variable declared within a block (i.e. a compound statement) has
scope only within that block.
C++ allows you declare variables anywhere within a program as
long as you follow the "declare before use" rule.
(C requires variable declarations at the beginning of a block).
Scope Example