Sunteți pe pagina 1din 6

Supplementary Notes for Campus Interview

Version 12.0

What is the difference between declaring a variable and defining a variable?


Declaring a variable means describing its type to the compiler but not allocating any space for it. Defining a variable means declaring it and also allocating space for it to hold the data values. You can also initialize a variable at the time it is defined. For data items, if I write: char ch; then that is a definition and storage is created. If instead I write: extern char ch; then that is a declaration and no storage is created.

term argument refers to the value that you supply corresponding to a parameter when you call a function. Parameters provide the means by which you pass information from the calling function into the function that is called. A variable or an expression or a constant can be used as an argument.

Points to remember
Functions cannot return arrays or functions although they can return pointers. There is no restriction on the possible number or type of parameters that may be associated with a function. The number of parameters a function has also directly affects the speed at which it is called the more parameters, the slower the function call. Therefore, if possible, you should minimize the number of parameters you use in a function. . One technique that can be helpful if you find yourself with a large number of function parameters is to put your function parameters in a structure. Function definitions may not be included within other function definitions, i.e. they cannot be nested. Function call is a prefix expression. Therefore when a function is used as a part of large expression, it will be evaluated first unless parentheses are used to specify a different evaluation order. Functions are identified by name and can return a single value.

About Function Call . . . . .


When a function is called in a C program, a block of storage is allocated on the stack to keep track of information associated with the call. Each call is referred to as activation. The block of storage placed on the stack is called an activation record or, alternatively, a stack frame. An activation record consists of five regions: incoming parameters, space for a return value, temporary storage used in evaluating expressions, saved state information for when the activation terminates, and outgoing parameters. Incoming parameters are the parameters passed into the activation. Outgoing parameters are the parameters passed to functions called within the activation. The outgoing parameters of one activation record become the incoming parameters of the next one placed on the stack. The activation record for a function call remains on the stack until the call terminates. When a function is called, space for its data area is allocated and placed on top of the run-time stack. On exit from the function, its data area is de-allocated and removed from the top of the run-time stack. Stack storage management is capable of dealing with recursive functions. In the recursive case we regard two recursive calls as being different so that we do not mix the data areas for one call with another, any more than we would mix the data areas for different functions, one called from within the other. This implies that there may be several data areas in existence simultaneously, one for each recursive call.

CONCEPT GLOBAL AND LOCAL VARIABLES


There are two common terms related to the visibility or accessibility of a variable. They are global and local variables. Variables declared within the function body are called local variables. They have local scope. Local variables are automatically created at the point of their declaration within the function body and are usable inside the function body. They are used without having any role in the communication between functions. Variables declared outside of all the functions of a program and accessible by any of these functions are called global variables. The existence and region of usage of these variables are not confined to any specific function body. These variables are known to all functions in the program and can be used by these functions as many times as may be required.
Page 1

Argument and parameter


The term parameter refers to a placeholder in the function definition that specifies the type of value that should be passed to the function when it is called. The

Supplementary Notes for Campus Interview

Version 12.0

If a variable of the same name is declared both within a function and outside of it, the function will use the variable that is declared within it and ignore the global one. If not initialized, a global variable is initialized to zero by default.

where use of global variables is advocated. Global variables, however, are extremely useful in creating array of data and constants that must be shared between many functions. If many functions require access to a group of arrays, global variables allow the functions to make efficient changes to the same array without the need for multiple arrays passing.

What does global or local mean?


How long memory will be associated with them is known as extent or lifetime of a data object. The following rules specify whether an identifier has global or local lifetime: Global lifetime: All functions have global lifetime. As do the identifiers declared at the top level (that is, outside all blocks in the program at the same level of function definitions). Local lifetime: An object (unless it is declared as static) is said to have local lifetime when it is created on entry to a block or function and destroyed on exit from block or function. Formal parameters and variables declared at the beginning of the block may have local lifetime depending on the place of declaration.

SCOPE
The region of the program over which an identifier is visible is called the scope of the identifier. The scope relates to the accessibility, the period of existence, and the boundary of usage of variables declared in a program.

Why is scope important?


In structured programming approach, the program is divided into independent functions that perform a specific task. The key word here is independent. For true independence, it is necessary for each function's variables to be isolated from interference caused by other functions. Only by isolating each function's data can you make sure that the function performs its intended task without affecting or being affected by some other part of the program. It is also true that in some situation complete data isolation between functions isn't always desirable. By specifying the scope of variables, a programmer may attain the control over the degree of data isolation.

The data object created with the use of special library functions such as malloc() or calloc() etc have dynamic duration and the storage remain allocated from the time of creation at run time until program termination or until a call to special library function free().

Types of Scope
Scopes can be of four types in C. o block o file o function o function prototype Block Scope This means that the identifier can only be used in the block in which it is declared. These variables are created at the point of their declaration inside the block and cease to exist outside it Functions are considered as named block. Variables declared within a function block can be used anywhere within the function in which they are defined.

A bit more about global variable


Rather than passing variables to a function as arguments, it is possible to make all variables global. But it is not recommended as global variables breaks the normal safeguards provided by functions. Using parameter passing mechanism and declaring local variables as needed, C offers provision for making functions independent and insulated from each other, including the necessity of carefully designating the type of arguments needed by a function, the variables used in the function, and the value returned. Using only global variables can be especially disastrous in larger programs that have many user-created functions. Since a global variable can be accessed and changed by any function following the global declaration, it is a time-consuming and frustrating task to locate the origin of an erroneous value. But it is not the case that use of global variables is always disadvantageous. There are certain instances

Page 2

Supplementary Notes for Campus Interview

Version 12.0

Function Scope This applies only to labels. Normally labels are used with goto statement. It simply means that labels can be used anywhere within the function in which they are defined. This includes use before definition. File Scope This means that the identifier can be used anywhere in the current file after the declaration of the identifier. This applies to functions and all variables declared outside functions. File scope variable is also known as global variable. Function Prototype Scope In order to improve readability function prototypes are usually written with "dummy" variable names. For example double max(double x, double y); The identifiers "x" and " y" have function prototype scope, which terminates at the end of the prototype.

Identifiers with file scope declared as static have internal linkage. These are known only within the file in which they are declared. Local identifiers have no linkage and are therefore known only within their own block. This includes the function's formal parameters (which can be treated like ordinary variables within the function) as well as definitions appearing within the function.

Two declarations of the same identifier in a single file that have the same linkage, either internal or external, refer to the same object. The same identifier cannot appear in a file with both internal and external linkage. For the three cases above, you will want external linkage, internal linkage, and no linkage respectively. The external linkage declarations would be prefixed with extern, the internal linkage declarations with static.
#include <stdio.h> // External linkage. extern int var1; // Definitions with external linkage. extern int var2 = 0; // Internal linkage: static int var3; // Function with external linkage void f1(int a){} // Function can only be invoked by name fro m within this file. static int f2(int a1, int a2) { return(a1 * a2); }

LINKAGE
An identifiers linkage determines which of the references to that identifier refer to the same object. C defines three types of linkages external, internal and no linkage. A variable with external linkage can be used anywhere in a multi-file program. A variable with internal linkage can be used anywhere in a single file, and a variable with no linkage can be used only in the block where it is defined. External linkage means they are available from the point of definition throughout the entire remaining text of the program, even across subsequently-compiled files. Internal linkage means internal to the file containing the program code. The scope of such a name is from the textual point of definition to the end of the file. i.e. you can refer to it in any line following the one in which it is defined. Variables with internal or external linkage can appear in more than one declaration, but variables with no linkage can be declared only once. In general, Functions and global variables have external linkage. This means they are available to all files that constitute a program.

Points to note
It is not always necessary to specify both the storage class and the type of identifiers in a declaration. Storage class specifiers appearing in declarations outside of functions are assumed to be extern. In a declaration inside a function, if a type but no storage class is indicated, the identifier is assumed to be auto. An exception to the latter rule is made for functions because auto functions do not exist. It is implicitly declared to be extern.

Page 3

Supplementary Notes for Campus Interview

Version 12.0

FUNCTION WITH VARIABLE LENGTH ARGUMENT

Storage class specifiers for functions


The only storage class specifiers that may be assigned with functions are extern and static. The extern signifies that the function can be referenced from other files- that is, the function name is exported to the linker. The static signifies that the function cannot be referenced from other files i.e. the function name is not exported to the linker. If no storage class appears in a function definition, extern is presumed. All the functions so far discussed accept a fixed number of arguments. But functions like printf() etc. accept any number of parameters. How can a function with variable number of arguments be written? To write such functions, macros defined in the header file stdarg.h have to be used. The presence of a variablelength argument list is indicated by an ellipsis in the prototype. For example, the prototype for printf(), as found in <stdio.h>, looks something like this:
extern int printf(const char *, ...);

Storage class specifiers for formal parameters


The only storage class specifier that can be used in a parameter declaration is register.

Default storage class specifier for variables


Variables declared within a function are considered to be class auto unless declared otherwise. The formal arguments to functions normally are class auto, but they can be made class register. Variables defined outside all functions are external

Those three dots ... allows the function to accept any number of parameters. Only the last parameters must be NULL and the function prototype must be as follows void function_name(const char *, ) ; The macros used are va_list, va_start(), va_arg(), and va_end(). va_list is an array or special pointer' type which is used in obtaining the arguments that come in place of ellipsis. va_start() begins the processing of an argument list, va_arg() fetches argument values from it, and va_end() finishes processing. Therefore, va_list is a little bit like the stdio FILE * type, and va_start is a bit like fopen(). Consider the following program.
#include <stdarg.h> #include <stdio.h> void show(int n, ...) { va_list ap; va_start(ap, n); printf("count = %d: ", n); while (n-- > 0) { int i = va_arg(ap, int); printf("%d ", i); } printf("\n"); va_end(ap); } int main() { show(1, 1); show(3, 1, 2, 3); return 0; }

atexit() function.
The function whose address is passed to atexit() gets called before the termination of program. If atexit() is called for more than one function then the functions are called in "first in last out" order. You can verify that from the output.
#include <stdio.h> #include <stdlib.h> void fun1(void) { printf("Inside fun1\n"); } void fun2(void) { printf("Inside fun2\n"); } int main(void) { atexit ( fun1 ) ; atexit ( fun2 ) ; printf ("This is the last statement\ of program?\n" ); return 0; }

Page 4

Supplementary Notes for Campus Interview

Version 12.0

The show() function declares a single parameter (n), followed by an ellipsis (...). The ellipsis specifies that a variable number of additional parameters are present. This means that a caller of show() can pass an arbitrary number of arguments in addition to the first int argument. The output of this C program is: count = 1: 1 count = 3: 1 2 3 There are some restrictions on functions with variablelength arguments. The first parameter must be present, since its name has to be passed to va_start(). While calling the function, if the type of the variable passed does not match the type expected in the function, the results are unpredictable. The C/C++ variable argument mechanism is quite useful in certain contexts. But the mechanism is error-prone, because it defeats type checking. For example, if the second show() call is changed to: show(3, 1, 2, 3.4); The result is something like this: count = 1: 1 count = 3: 1 2 858993459 The program assumes that an int argument has been passed, when in fact a double (3.4) is passed. The macro va_end() performs cleanup operations. It releases any memory that might have been allocated when va_start() was called. Another function vprintf() used to develop a function that outputs an error and exits.
void error(const char *fmt) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); exit(0); }

Notice that the function error() is called just like printf(). RECURSION

When Recursion is Useful


Recursion might not be the most efficient way to implement an algorithm. Each time a function is called; there is a certain amount of "overhead" that takes up memory and system resources. Recursion is of value when the return values of the recursive function are used in further processing within the calling version of the function (rather than being immediately passed back to an earlier version of the function). In this case it was worth saving the parameter and local variables on the stack because they are used later in some useful way. If one problem can be solved in both way (recursive or iterative), then choosing iterative version is a good idea since it is faster and doesn't consume a lot of memory.

When not to use recursion


Recursion, of course, is an elegant programming technique, but not the best way to solve a problem, even if it is recursive in nature. This is mainly due to the following reasons: 1. It requires stack implementation. 2. It makes inefficient utilization of memory, as every time a new recursive call is made a new set of local variables is allocated to function. 3. Moreover it also slows down execution speed, as function calls require jumps, and saving the current state of program onto stack before jump. The following are some of the important points, which differentiate iteration from recursion.

Recursion Vs Iteration
Iteration It is a process of executing a statement or a set of statements repeatedly, until some specified condition is specified. Iteration is more of a bottom up approach. It Recursion Recursion is the technique of defining anything in terms of itself.

Use of above function which prompts the user to enter an integer greater than 0, failing of which it outputs an error message and exits.
printf(\n enter an integer >0); scanf(%d, &n); if(n<=0) error(value of n= %d it must be\ greater than 0 \n, i);

Recursion is a top down approach to problem

Page 5

Supplementary Notes for Campus Interview


begins with what is known and from this constructs the solution step by step. Any recursive problem can be solved iteratively. Iterative counterpart of a problem is more efficient in terms of memory utilization and execution speed. solving. It divides the problem into pieces or selects out one key step, postponing the rest. Not all problems recursive solution. have

Version 12.0 #include <stdio.h> int main() { main(); return 0; }

Recursion is generally a worse option to go for simple problems, or problems not recursive in nature.

Why do array subscripts starts at 0 instead of 1?


It can make array subscripting somewhat faster. Two facts are known about an array. Firstly, an array name say arr always designates the base address of the array. Secondly, address of ith element of arr is given by &arr[i], which is eventually (arr + i). The base address is the address of the first element is nothing but address of the first element which is &a[0]. That means that both arr and &a[0] holds the same value which is the address of the first element of the array. To carry the expression (arr+i) same equivalence for all the elements of the array, subscript of the first element must be 0. Having subscript starts at 0 simplifies scaling a bit for the compiler.

FAQ

Why is a function prototype required?


A function prototype tells the compiler what kind of arguments a function receives and what kind of value a function is going to give back to the calling function. Function prototype helps the compiler ensure that calls to a function are made correctly and that no erroneous type conversions are taking place. If the compiler finds any difference between the prototype and calls to the function or the definition of the function, an error or a warning may be caused.

Can main() be called recursively?


This is perfectly legal to call main() recursively if properly written as follows#include <stdio.h>
int main() { static int c=5; if(c-->0) { printf("\t %d", c); return main(); } else return 0; }

Why do have a null character (\0 or NUL) at the end of a string?


A string is not a data type but a data structure. This means that its implementation is logical not physical. The physical data structure is the array in which string is stored. Since string, by definition, is a variable length structure, it is needed to identify the logical end of the data within the physical structure.

If a string str contains a string literal Oxford University Press, then is it legal to print the string using the statement printf(str);?
Yes. It prints Oxford University Press on the screen.

Output:
4 3 2 1 0 If the recursive call does not have base case as the following program then this will go on till a point where runtime error occurs due to stack overflow.

Page 6

S-ar putea să vă placă și