Notes
Notes
2. The signed qualifier is redundant because the integral types are signed unless you
specify the unsigned qualifier.
3. C++ supports three kinds of floating-point numbers, which are distinguished by their
precision. These are float, double and long double.
Standard C++ does not specify the range of values that floating point numbers can
contain. These ranges depend on the particular implementation of the C++ language.
The standard defines a header file, <cfloat>, with global symbols that identify the
ranges.
-- String constants are exception. For string constants compiler finds a place
in memory and compiles the address of the string constant into the
statement. e.g. cp = “Hello”;
5. A variable that receives an assigned value is called an lvalue, because it’s reference
appears on the left side of the assignment. The expression that provides the assigned
value is called an rvalue, because it is on the right side of the assignment. A constant,
for example, is an rvalue but can not be an lvalue.
-- (FirstTotal = SecondTotal) = 0;
6. Initializers –
Variables that are declared inside other functions and statement blocks are initialized
every time the function or statement block begins execution. An exception is static
local variable which is initialized the first time it is declared and never again.
If the variable is global or static, the initializing
expression must be a constant value. In other words, it can not contain any function
calls, references to other variables, or increment and decrement operators.
There are two formats for coding initializers in C++ –
-- char ch(‘a’);
-- char ch = ‘a’;
This behaviour is a by-product of the C++ this pointer and the overloaded <<
operator for ostream objects.
8. The difference between sending std::endl and the new-line character to std::cout
object is that the std::endl manipulator flushes the output stream after sending a new-
line character, whereas the new-line character alone does not.
9. The C++ compiler provides the startup and shutdown procedures when you compile
and link the program. The system’s startup procedure calls main() to begin running
the program. When main() returns, system’s shutdown procedures take over.
C++ applies a process called name mangling to the compiler’s internal identifier of a
function. The mangled name includes tokens that identify the function’s return type
and the types of it’s arguments. Calls to the function and the function definition itself
are recorded in the relocatable object file as references to the mangled name – which
is unique even though several functions can have the same unmangled name.
Although C++ mangles the names, other languages do not. This
presents a problem, because a C++ program must be able to call functions that are
compiled or assembled in other languages and, C++ must be able to provide functions
that can be called from other languages.
But without some method for telling C++ compiler not to mangle calls to those
functions or function definitions itself, we can’t achieve it. Therefore C++ has a
concept of linkage specifications. We can tell the C++ compiler when a function has
been compiled with different linkage conventions.
The following code shows how a linkage specification tells the compiler that a C
compiler compiled the functions in a header file.
extern “C”
{
#include “header.h”
}
int main()
{
funInHeader(); //Call is not mangled
}
Language environments that support both languages manage the translation for you
by hiding the linkage specifications in the Standard C Library header files for the C
functions. The GNU compiler uses the convention shown in the following code
fragment –
11. Compiler header files with names that begin with “c”, and that have no file extension,
contain declarations for the standard C library functions. E.g. <cmath> , <cstring>
etc. Standard C++ includes the complete Standard C library
12. The condition tested by the switch statement must be an integral expression. This
means that it can contain operators and function calls. The values tested by the case
statements must be constant integral values. This means that they can have constant
expressions and operators but can not have variables, function calls or side effects
such as assignments and increment and decrement operators.
There may be only one default statement in a switch
if(ch == ‘y’)
goto done;
int var = 1;
done:
return 0;
}
The program does not compile, because the goto statement jumps over the
initialization of the variable var. The theory is that a variable that needs initialization
must be guaranteed to have undergone that initialization as long as the variable is in
scope.
If you were permitted to jump around the initialization of an object, it’s subsequent
destruction which the compiler invokes, assuming that the object’s initialization
occurred – can cause undesirable consequences.
The restriction described above does not apply to C language goto, which
permits such jumps, assuming that the programmer takes responsibility for the
integrity of all variables under such circumstances. But C variables do not involve
the kind of construction and destruction often found in C++ class objects.
if(ch == ‘y’)
goto done;
//----------------
int var; // Initializer replaced with an assignment;
var = 1;
//----------------
done:
return 0;
}
if(ch == ‘y’)
goto done; //goto jumps over entire scope of variable
var
else
{
//----------------
int var = 1; //Scope of variable restricted to else
//----------------
}
done:
return 0;
}
14. Application of static storage class specifier to function declarations and external
variables --
It declares identifiers with file scope, i.e. makes them available only to the functions
in the translation unit in which they are defined. It hides the identifiers of functions
and variables from other source code files linked into the same program.
-- External global identifiers are in scope throughout the program. They are
visible to all object modules in the application program, in third party class and
function libraries, and in the compiler’s system libraries. When two variables in
global scope have the same identifier, the linker generates an error. This usage of
static storage class was targeted to solve the above problem.
However, C++ has introduced the concept of namespaces that has
virtually eliminated the need for any program to make use of the above concept.
Although the scope of local static variable begins inside the statement block in which
the variable is declared and ends when the block terminates, the variable itself retains
its value between executions of the statement block. Initializers are effective only for
the first execution of the statement blocks.
NOTE –
-- Local static variable is not of file scope instead it’s scope is within the block in
which it is declared.
-- Lifetime of variable is same as the lifetime of the program.
16. The extern storage class declares external variables that have not been defined yet,
but that the program needs to reference or that are defined in different translation unit.
Compiler compiles the references to external variables as unresolved references.
These references are resolved at the time of linking.
Some facts –
17. The purpose of register storage class is to allow programmer to specify conditions
under which the program’s performance can be improved if certain local, automatic
variables are maintained in one of the computer’s hardware registers. The register
storage class is only a suggestion to the compiler. The compiler can ignore the
suggestion. You can not take the address of the register variables, because hardware
registers on most computers do not have memory addresses. The address restriction
applies even when the compiler chooses to ignore the suggestion and puts the variable
in addressable memory.
18. The const variable might or might not occupy memory, have an address, and be used
in any context that does not modify the contents of the variable. Whether it has an
address depends on how you use it and on the C++ compiler implementation. If you
take the address of a const variable, the compiler must give it a memory location.
Otherwise, the compiler is free to treat a reference to the expression as if it were
coded as a constant in an expression.
struct A
{
int one;
int two;
int three;
}
struct Sample
{
int first;
int second;
int third;
A a;
}
int main()
{
union
{
int quantity_todate;
int quantity_balance;
};
quantity_todate -= quantity_sold;
return 0;
}
You initialize an array by following its definition with a brace-enclosed initializer list.
There may be as many initializers as there are elements in the array, as shown below
here –
If you code more initializers than there are elements in the dimension, a compiler
error occurs. If you code fewer, the remaining elements are initialized with zero
values.
cout<< “Hello”;
The compiler builds an internal unnamed array like this –
The compiler passes the address of the internal array to the cout object which can
recognize a pointer to type char. You can not declare an un-named character array
yourself. Only compiler can do that. But you can always initialize a character array
with string constant as follows –
23. Pointers usually are of uniform size regardless of what they point to, and you can
coerce any value into one of them and dereference that value as if it were the address
of a variable of the pointer’s type. However, you must go out of your way to get the
C++ compiler to let you put into a pointer the address of data of a different type.
When you compile programs for computers that have segmented memory
architecture, pointers to functions and pointers to data can have different sizes in
programs compiled with different data and code memory models.
24. The ++ auto increment operator has less precedence than the * dereferencing
operator, so the expression just shown retrieves what ptr points to and then
increments ptr.
std::cout<<*ptr++<<std::endl;
Sometimes you may want to increment the value rather than the pointer. So you code
the expression like this –
(*ptr)++
-- You can not dereference Void Pointer unless you provide a cast.
-- You can not perform pointer arithmetic on a Void Pointer without a cast.
-- You return Void Pointers from functions to assign to any of several different
kinds of pointers. E.g. malloc function returns void *.
-- C++ does not allow implicit conversion from a void pointer to another pointer
type [Although C does].
o Code Segment
It contains the executable code of the program.
o Data Segment
It contains all the statically allocated data. E.g. Aggregate
initialization of arrays.
o Stack Segment
Maintains local data objects, function arguments, and the linkage
from a calling function to a called function.
o Extra Segment
Not known
Depending on the operating platform and the compiler, the heap and stack can be
operating system resources that are shared by all concurrently running programs, or
they can be local resources owned exclusively by the programs that use them.
A reference must be initialized when you declare it unless one of the following
statements is true –
NOTE
-- You must not return a reference to an automatic variable because the automatic
variable goes out of scope when the function returns. Therefore, you are returning
a reference to a variable that no longer exists. Sometimes the program appears to
work because the stack location where the automatic variable existed is intact
when the reference is used. A program that appears to work in some cases can fail
in other
Date& getDate(void)
{
Date dt = {6, 24, 40};
return dt; // Bad – reference to auto variable
}
-- Reference can not be null. But nothing in the language or in any C++ compiler
prevents you from using the idiom or equally troublesome variation :
Object * pObject = 0;
Object& rObject = *pObject; //refers to invalid object
-- Preprocessing directives are lines of code that begin with a pound sign (#). The
pound sign must be the first character on a line of code after any optional white
space. The entire line is devoted to the directive, which affects the translation of
the source code to be passed to the compiler.
-- While defining macros, parentheses around the macro definition’s expression are
not necessary, but their use is prudent.
-- All the macros with parameters can be functions. What is the advantage of macros
then? The advantage is that macro expands to inline code. No function call
overhead is involved when you call a macro.
C++’s inline function feature provides an improved facility for writing macros.
Inline functions are similar to macros with the exception that they are not subject
to macro side effects.