|
|
|
|
Lesson#7
|
Calling Conventions Storage classes and
Variable Scope
|
|
|
|
Calling
Convention................................................................................................2
Difference between __stdcall and __cdecl calling
convention...........................2
Default Calling Convention for C programmes
..................................................2
Default Calling Convention for Windows
Programmes......................................3
Storage Class
Modifiers........................................................................................4
1. Auto storage class
............................................................................................4
Example:
...........................................................................................................4
2. Register - Storage
Class...................................................................................5
Initialization
.......................................................................................................5
3. Static Storage Class
.........................................................................................6
Example:
...........................................................................................................6
Example:
...........................................................................................................6
Initialization
.......................................................................................................7
Storage Allocation
.............................................................................................7
Block Scope Usage
...........................................................................................7
File Scope Usage
..............................................................................................8
4. Extern Storage Class
........................................................................................8
Initialization
.......................................................................................................9
Storage Allocation
.............................................................................................9
Scope, Initialization and Lifetime of Variable
........................................................9
Points to be
considered:..................................................................................10
Stack...................................................................................................................10
Note.................................................................................................................10
Application of Stacks
.......................................................................................11
Const Access Modifier
........................................................................................12
Constant Variables
..........................................................................................12
Command Line Arguments
.................................................................................12
Summary
............................................................................................................14
Tips
.....................................................................................................................13
Calling Conventions, Storage classes and Variable Scope 2
Calling Convention
To call a function, you must often pass parameters to it. There are plenty
of ways how
this can be done. You either pass the parameters on the calling stack (place
where the
processor also places the temporary pointer to the code following the call,
so it knows
where to continue after the call was done), or you pass some of them in
registers. Floating
point values can also be passed on the stack of the coprocessor.
Calling conventions rule how parameters will be passed (stack only or
registers), in
which order they will be passed (from left to right, i.e. in the same order
as they appear in
source code, or the other way around), and which code will clean the stack
after use, if
necessary. There are a lot of possible combinations:
• pascal, the original calling
convention for old Pascal programs;
•
register, the
current default calling convention in Delphi;
•
cdecl, the standard
calling convention for C and C++ code;
•
stdcall, the default
cross-language calling convention on 32-bit Windows;
•
safecall, a special
case of stdcall, which can be ignored for now.
Difference between __stdcall and __cdecl calling
convention
cdecl and __stdcall just tells the compiler whether the called
function or the calling
function cleans up the stack. In __stdcall calling convention, the called
function cleans up
the stack when it is about to return. So if it is called in a bunch of
different places, all of
those calls do not need to extra code to clean up the stack after the
function call.
In __cdecl calling convention, it is the caller function that is responsible
for cleaning the
stack, so every function call must also need to include extra code to clean
up the stack
after the function call.
Default Calling Convention for C programmes
The __cdecl is the default calling convention for C programs. In this
calling convention,
the stack is cleaned up by the caller. The __cdecl calling convention
creates larger
executables than __stdcall, because it requires each function call to
include stack cleanup
code.
The following list shows the implementation of _cdecl calling convention.
Element Implementation
Argument-passing order Right to left
Calling Conventions, Storage classes and Variable Scope 3
Stack-maintenance responsibility Calling function pops the arguments from
the
stack
Name-decoration convention Underscore character (_) is prefixed to names
Case-translation convention No case translation performed
Default Calling Convention for Windows
Programmes
The __stdcall calling convention is used to call Win32 API functions.
The callee cleans
the stack
Functions that use this calling convention require a function prototype.
return-type __stdcall
function-name[(argument-list)]
The following list shows the implementation of this calling convention.
Element Implementation
Argument-passing order Right to left.
Argument-passing convention By value, unless a pointer or reference type is
passed.
Stack-maintenance responsibility Called function pops its own arguments from
the
stack.
Name-decoration convention An underscore (_) is prefixed to the name. The
name is followed by the at sign (@) followed by
the number of bytes (in decimal) in the argument
list. Therefore, the function declared as int func(
int a, double b ) is decorated as follows:
_func@12
Case-translation convention None
Calling Conventions, Storage classes and Variable Scope 4
Storage Class Modifiers
C has a concept of 'Storage classes'
which are used to define the scope (visibility) and life
time of variables and/or functions.
1. Auto storage class
The default storage class for local variables is “auto storage class”. The
auto storage class
specifier lets you define a variable with automatic storage; its use and
storage is restricted
to the current block. The storage class keyword
auto is optional
in a data declaration. It is
not permitted in a parameter declaration. A variable having the auto storage
class
specifier must be declared within a block. It cannot be used for file scope
declarations.
Because automatic variables require storage only while they are actually
being used,
defining variables with the auto storage class can decrease the amount of
memory
required to run a program. However, having many large automatic objects may
cause you
to run out of stack space.
Example:
{
int Count;
auto int Month;
}
The example above defines two variables with the same storage class. auto
can only be
used within functions, i.e. local variables.
Declaring variables with the auto storage class can also make code
easier to maintain,
because a change to an auto variable in one function never affects
another function
(unless it is passed as an argument).
Initialization
You can initialize any auto variable except parameters. If you
do not initialize an
automatic object, its value is indeterminate. If you provide an initial
value, the expression
representing the initial value can be any valid C expression. For structure
and union
members, the initial value must be a valid constant expression if an
initializer list is used.
The object is then set to that initial value each time the program block
that contains the
object's definition is entered.
Note: If you use the goto statement to jump into the middle of a
block, automatic
variables within that block are not initialized.
Storage Allocation
Calling Conventions, Storage classes and Variable Scope 5
Objects with the auto storage class specifier have automatic storage
duration. Each time a
block is entered; storage for auto objects defined in that block is
made available. When
the block is exited, the objects are no longer available for use.
If an auto object is defined within a function that is recursively
invoked, memory is
allocated for the object at each invocation of the block.
2. Register - Storage Class
Register storage class is used to define local variables that should be
stored in a register
instead of RAM. This means that the variable has a maximum size equal to the
register
size (usually one word) and cant have the unary '&' operator applied to it
(as it does not
have a memory location).
{
register int Miles;
}
Register should only be used for variables that require quick access - such
as counters. It
should also be noted that defining 'register' does not mean that the
variable will be stored
in a register. It means that it MIGHT be stored in a register - depending on
hardware and
implementation restrictions.
• The register storage class specifier indicates to the compiler that a
heavily used
variable (such as a loop control variable) within a block scope data
definition or a
parameter declaration should be allocated a register to minimize access
time.
• It is equivalent to the auto storage class except that the compiler places
the object,
if possible, into a machine register for faster access.
• An object having the register storage class specifier must be
defined within a
block or declared as a parameter to a function.
The following example lines define automatic storage duration objects using
the
register storage class specifier:
register int score1 = 0, score2 = 0;
register unsigned char code = 'A';
register int *element = &order[0];
Initialization
You can initialize any register object except parameters. If
you do not initialize an
automatic object, its value is indeterminate. If you provide an initial
value, the expression
representing the initial value can be any valid C expression. For structure
and union
members, the initial value must be a valid constant expression if an
initializer list is used.
Calling Conventions, Storage classes and Variable Scope 6
The object is then set to that initial value each time the program block
that contains the
object's definition is entered.
• Objects with the register storage class specifier have automatic
storage duration.
Each time a block is entered, storage for register objects defined in
that block are
made available. When the block is exited, the objects are no longer
available for
use.
• If a register object is defined within a function that is
recursively invoked, the
memory is allocated for the variable at each invocation of the block.
3. Static Storage Class
Static is the default storage class for global variables. An object having
the static storage
class specifier can be defined within a block or at file scope. If the
definition occurs
within a block, the object has no linkage. If the definition occurs at file
scope, the object
has internal linkage.
Example:
Two variables below (count and road) both have a static storage
class. Static variables
can be 'seen' within all functions in this source file. At link time, the
static variables
defined here will not be seen by the object modules that are brought in.
static int Count;
int Road;
main()
{
printf("%d\n", Count);
printf("%d\n", Road);
}
'static' can also be defined within a function! If this is done the variable
is initialized at
run time but is not re initialized when the function is called.
Example:
There is one very important use for 'static'. Consider this bit of
code.
char * func(void);
main()
{
char *Text1;
Text1 = func();
}
Calling Conventions, Storage classes and Variable Scope 7
char * func(void)
{
char Text2[10]="martin";
return(Text2);
}
Now, 'func' returns a pointer to the memory location where 'text2' starts
BUT text2 has a
storage class of 'auto' and will disappear when we exit the function and
could be
overwritten but something else. The answer is to specify:
static char Text[10]="martin";
The storage assigned to 'text2' will remain reserved for the duration of the
program.
Initialization
We can initialize any static object with a constant expression
or an expression that
reduces to the address of a previously declared extern or static
object, possibly modified
by a constant expression. If you do not provide an initial value, the object
receives the
value of zero of the appropriate type.
Storage Allocation
Storage is allocated at compile time for static variables that are
initialized. Un initialized
static variables are mapped at compile time and initialized to 0 (zero) at
load time. This
storage is freed when the program finishes running. Beyond this, the
language does not
define the order of initialization of objects from different files.
Block Scope Usage
Use static variables to declare objects that retain their
value from one execution of a
block to the next execution of that block. The static storage class
specifier keeps the
variable from being reinitialized each time the block, where the variable is
defined, runs.
For example:
static float rate = 10.5;
Initialization of a static array is performed only once at compile
time. The following
examples show the initialization of an array of characters and an array of
integers:
static char message[] = "startup completed";
static int integers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Calling Conventions, Storage classes and Variable Scope 8
File Scope Usage
The static storage class specifier causes the variable to be
visible only in the file where it
is declared. Files, therefore, cannot access file scope static
variables declared in other
files.
Restrictions
We cannot declare a static function at block scope.
4. Extern Storage Class
Extern defines a global variable that is visible to all object modules. When
you use
'extern' the variable cannot be initialized as all it does is to point the
variable name at a
storage location that has been previously defined.
With extern keyword, we are actually pointing to such a variable that is
already been
defined in some other file.
Source 1 Source 2
-------- --------
extern int count; int count=5;
write() main()
{ {
printf("count is %d\n", count); write();
}
}
Count in 'source 1' will have a value of 5. If source 1 changes the value of
count - source
2 will see the new value
The extern storage class specifier lets you declare objects and
functions that several
source files can use. All object declarations that occur outside a function
and that do not
contain a storage class specifier declare identifiers with external linkage.
All function
definitions that do not specify a storage class define functions with
external linkage.
An extern variable, function definition, or declaration also makes
the described variable
or function usable by the succeeding part of the current source file. This
declaration does
not replace the definition. The declaration is used to describe the variable
that is
externally defined.
Calling Conventions, Storage classes and Variable Scope 9
If a declaration for an identifier already exists at file scope, any
extern declaration of the
same identifier found within a block refers to that same object. If no other
declaration for
the identifier exists at file scope, the identifier has external linkage.
An extern declaration can appear outside a function or at the
beginning of a block. If the
declaration describes a function or appears outside a function and describes
an object
with external linkage, the keyword extern is optional.
If we do not specify a storage class specifier, the function has external
linkage.
Initialization
We can initialize any object with the extern storage class specifier
at file scope. Similarly,
we can also initialize an extern object with an initializer that must
either:
• Appear as part of the definition and
the initial value must be described by a
constant expression. OR
• Reduce to the address of a
previously declared object with static storage duration.
This object may be modified by adding or subtracting an integral constant
expression.
If we do not explicitly initialize an extern variable, its initial
value is zero of the
appropriate type. Initialization of an extern object is completed by
the time the program
starts running.
Storage Allocation
Storage is allocated at compile time for extern variables that
are initialized. Uninitialized
variables are mapped at compile time and initialized to 0 (zero) at load
time.
This storage is freed when the program finishes running.
Scope, Initialization and Lifetime of Variable
In the following section, we will discuss the scope and lifetime of
variables.
Example:
Consider the example below:
int main ()
{
float temp = 1.1;
int a;
int b;
printf ("Value for a and b [int]: ");
Calling Conventions, Storage classes and Variable Scope 10
scanf ("%d%d", &a, &b);
if ( a < b )
{
int temp = a; /* this "temp" hides the other one */
printf ("Smallest local ""temp"" = a*2 = %d\n", 2*temp);
} /* end of block; local "temp" deleted */
else
{
int temp = b; /* another "temp" hides the other one */
printf ("Smallest local ""temp"" = b*3 = %d\n", 3*temp);
} /* end of block; other local "temp" deleted */
printf ("Global ""temp"" used: %f\n", a * b + temp);
return 0;
}
Points to be considered:
• each { } block creates
a new scope
• variables declared and initialized
in a scope are deleted when execution leaves
scope
• note the f-format to print result
with global variable
Stack
A stack is an abstract data type that permits insertion and deletion
at only one end called
the top. A stack is a collection of items in which only the most
recently added item may
be removed. The latest added item is at the top. Basic operations are push
and pop.
Note
Description of elements: A stack is defined to hold one type of data
element. Only
the element indicated by the top
can be accessed. The elements are related to each
other by the order in which they are put on the stack.Description of
operations: Among the standard operations for a stack are:
• insert an element on top of the stack (push)
• remove the top element from the stack (pop)
• Determine if the stack is empty.
Calling Conventions, Storage classes and Variable Scope 11
An example of a stack is the pop-up mechanism that holds trays or plates in
a cafeteria.
The last plate placed on the stack (insertion) is the first plate off the
stack (deletion). A
stack is sometimes called a Last-In, First-Out or LIFO data
structure. Stacks have
many uses in computing. They are used in solving such diverse problems as
"evaluating
an expression" to "traversing a maze."
Application of Stacks
A stack data structure is used when subprograms are called. The
system must remember
where to return after the called subprogram has executed. It must remember
the contents
of all local variables before control was transferred to the called
subprogram. The return
from a subprogram is to the instruction following the call that originally
transferred
control to the subprogram. Therefore, the return address and the local
variables of the
calling subprogram must be stored in a designated area in memory. For
example,
suppose function A has control and calls B which calls C which calls D.
While D is
executing, the return stack might look like this:
The first "return" would return (from D) to the return address in Function C
and the
return stack would then look like:
The last function called is the first one completed. Function C cannot
finish execution
until Function D has finished execution. The sequence in which these
functions are
executed is last-in, first-out. Therefore, a stack is the logical data
structure to use for
Calling Conventions, Storage classes and Variable Scope 12
storing return addresses and local variables during subprogram invocations.
You can see
that the "stack" keeps the return addresses in the exact order necessary to
reverse the
steps of the forward chain of control as A calls B, B calls C, C calls D.
Const Access Modifier
The const keyword is used to create a read only variable. Once initialized,
the value of
the variable cannot be changed but can be used just like any other variable.
const int i = 10; // “i ” cannot be changed in the programme.
Constant Variables
Consider the following examples:
Constant pointer to variable data:
char * const ptr = buff. // constant pointer to variable data
*ptr = ‘a’;
ptr = buff2; // it will be an error
since we have declared ptr as a “constant pointer to variable data”, so we
can change the
contents of the place where ptr is pointing at, i.e. data but being a
constant variable, the
ptr value i.e. the address it contains cannot be modified.
• Variable pointer
to Constant data: const char * ptr = buff. //variable pointer to
constant data
*ptr = ‘a’; // it will be an error
ptr = buf2;
Here, ptr has been declared as “variable pointer to constant data”. In this
case, the data to
which the ptr is pointing to remains constant and cannot be modified after
initialization.
The contents of ptr (address) are variable and we can change the contents of
ptr.
Command Line Arguments
C provides a fairly simple mechanism for retrieving command line parameters
entered by
the user. It passes an argv parameter to the main function in the program.
int main(int argc, char *argv[])
{
… … …
}
Calling Conventions, Storage classes and Variable Scope 13
In this code, the main program accepts two parameters, argv and argc. The
argv
parameter is an array of pointers to string that contains the parameters
entered when the
program was invoked at the command line. The argc integer contains a count
of the
number of parameters.
Tips
• Remember the calling conventions used by the
functions you are using. It will
give you a clearer image of what happens when some parameters are passed to
a
function.
• Automatic variables require storage only
while they are actually being used, so
defining variables with the auto storage class can decrease the amount of
memory
required to run a program.
• Avoid defining many large automatic objects
as it may cause you to run out of
stack space.
• Register access modifier should only be used
for variables that require quick
access - such as counters.
• Use static variables to declare objects that
retain their value from one execution of
a block to the next execution of that block since the static storage class
specifier
keeps the variable from being reinitialized each time the block runs.
• An extern declaration can appear outside a
function or at the beginning of a block.
If the declaration describes a function or appears outside a function and
describes
an object with external linkage, the keyword extern is optional.
• Please note that variables declared and
initialized in a scope are deleted when
execution leaves scope.
• A stack data structure is used when
subprograms are called. It is the logical data
structure to use for storing return addresses and local variables during
subprogram
invocations.
• Do not try to change the value of a constant
variable declared with “const”
keyword after it has been initialized.
Calling Conventions, Storage classes and Variable Scope 14
Summary
The calling conventions tells us in which order the parameters will be
passed in a
function and whether the calling function or the called function is
responsible for the
cleaning of the stack.
The default calling convention for C programs is __cdecl and in this
convention, the
caller is responsible for cleaning the stack after the function call.
Similarly, the default calling convention for the windows programs is
__stdcall. Here the
called function itself has to do the stack clean up and so no extra code is
required for
stack clean up with each function call. It is very obvious that the __cdecl
calling
convention creates larger executables because it requires each function call
to include the
clean up code.
Storage classes are used to describe the scope and visibility of the
variables and
functions. The common storage classes discussed above are auto, register,
static, and
extern etc.
In the lifetime of variables, we have discussed that each { } block creates
a new scope.
Variables declared and initialized in a scope are deleted when execution
leaves that scope
The const keyword is used to create a read only variable. Thus constant
variables are not
allowed to be modified after initialization.
Command line arguments provide an easy way to pass some parameters to the
programme in the main function when the programme execution starts. When
using an
executable that requires startup arguments to debug, you can type these
arguments at the
command line, or from within the development environment.
|
|
|
|