G A T E F O R S T U D E N T S - Essence of C

Contact
Computer Sciences
=> C-aptitude (21-40)
=> C-aptitude (41-60)
=> C-aptitude (61-90)
=> C-aptitude (91-120)
=> C-aptitude (121-178)
=> Operating system -1
=> Refresher for Interview
=> Essence of C
=> Computer Basics
=> C++ Aptitude-1
=> Technical Aptitude-1
=> C++ Aptitude-2
=> Networking
=> CTS - 1
=> CTS - 2
=> UNIX Section I
=> UNIX Section II
=> UNIX Section III
=> C-aptitude (1-20)
=> Windows Xp OS Format
=> An A-Z Index of the Windows XP command line
=> Command-line reference A-Z
Physics
Chemistry
Maths
Commerce
Exam Alerts (New)
General aptitude
Company Informations
Personality Development
Body Language
Facing Interviews
Group Discussion
Educational News
LIST OF E-BOOK SITES
Health Tips
Subjects Gateways
Innovative sciences
Life sciences



 

 

Essence of C
5 - POINTERS
Pointers, Pointer Operators, Pointer Expressions, Pointers and Arrays, Multiple Indirection, Pointer to Functions
 
A pointer is a variable which holds a memory address, that address usually being the address of another variable. Pointers provide the means by which functions may modify their calling parameters. They also support C's dynamic allocation functions and improve the efficiency of certain routines.
 
If a variable is going to hold a pointer, it must be declared as such. The general form of declaration is:
 
type *name;
 
where type is any valid C data type and name is the name of the pointer variable. The base type defines what type of variables the pointer can point to. All pointer arithmetic is done relative to the base type.
 
Pointer Operators
The & Operator
 
The & operator is a unary operator (ie, an operator which requires only one operand) which returns the memory address of the operand. For example:
 
 
 
    m = &count;
 
places the memory address of count into m.
 
The * Operator
 
The * operator is the complement of & in that it returns the value of the variable at the address which follows. For example:
 
 
 
    q = *m;
 
places the value of count into q.
 
Pointer Expressions
Pointer Assignments
 
As with any variable, a pointer may be used on the right side of an assignment operator to assign its value to another pointer.
 
Pointer Arithmetic
 
The only arithmetic operations which may be used on pointers are addition and subtraction. When, say, an int pointer is incremented (eg, p++;), the address held by the pointer will be incremented by four, not by 1, the reason being that integers are (normally) four bytes long. That is, pointers are incremented and decremented relative to the length of their base type.
 
Arithmetic operations are not limited to the increment and decrement operators. Integers may be added to, or subtracted from, pointers, as in:
 
 
 
    p = p + 12;
 
Pointer Comparisons
 
Pointers may be compared in a relational expression, as in:
 
 
 
    if(p < q)
   printf("p points to lower memory than q");
 
Pointers and Arrays
 
C provides two methods for accessing array elements, namely, array indexing and pointer arithmetic. Pointer arithmetic can be faster than array indexing.
 
In the following, p is set to point to the first element of str:
 
 
 
    char str[80], *p;
    p = str;
 
Two ways to access the fifth element of str are as follows:
 
 
 
    str[4]; // Array indexing.
    *(p+4); // Pointer arithmetic.
 
The following examples illustrate the two methods:
 
    // Index s as an Array
 
    void puts(char *s)
    {
      register int t;
 
      for(t=0;s[t];t++) }
        putchar(s[t]);
    }
 
    // Access s as a Pointer
 
    void puts(char *s)
    {
      while(*s)
        putchar(*s++);
    }
 
Most professional C programmers would find the second method easier to read and understand.
 
Arrays of Pointers
 
Pointers may be arrayed like any other data type, e.g.:
 
 
 
    int *x[10];
 
Assigning the address of an int variable to the third element of this pointer array is achieved by:
 
 
 
    x[2] = &var;
 
Finding the value of var is achieved by:
 
 
 
    a = *x[2];
 
An array of pointers may be passed to a function using the same method used to pass other arrays, i.e., by calling the function with the array name without any indexes, as in:
 
 
 
    void display_array(int *q[])
    {
      int t;
 
      for(t=0;t<10;t++)
        printf("%d ",*q[t]);
    }
 
in which q is not a pointer to integers but to an array of pointers to integers.
 
Pointer arrays are often used to hold pointers to strings, as in:
 
 
 
    void syntax_error(int num)
    {
      static char *err[] =
      {
        "Cannot open filen",
        "Read errorn",
        "Write errorn",
      }
      printf("%s", err[num]);
    }
 
Multiple Indirection
 
Multiple indirection is where a pointer points to another pointer that points to a target value. A variable which is a pointer to a pointer must be declared as such, as in:
 
 
 
    float **balance;
 
Initializing Pointers
 
Before a pointer is assigned a value, it contains an unknown value. If used in this state, it could crash the operating system. The value null should be assigned to a pointer that points nowhere.
 
As previously illustrated, strings may be initialized as follows:
 
 
 
    char *p = "hello worldn";
 
The reason this sort of initialization works is because of the way the compiler operates. All C compilers create what is known as a string table. Therefore, the above declaration places the address of "hello world", as stored in the string table, into p. p can then be used like any other string, as in:
 
 
 
    printf(p);
 
Pointers to Functions
 
Even though a function is not a variable, it has a location in memory which may be assigned to a pointer. A variable which is a pointer to a function must be declared as such, as in:
 
 
 
    int (*p)();
 
The address of a function is assigned to this variable by using the function's name without parentheses or arguments, e.g.:
 
 
 
    p = function_name;
 
C's Dynamic Allocation Functions
 
Global variables are allocated storage at compile time and local variables use the stack. Neither can be added during program execution. Dynamic allocation is the means by which a program can obtain memory during execution. The core of the dynamic allocation system consists of the functions malloc() (allocates memory from the heap) and free() (frees that memory). malloc() returns a pointer to the first byte of the allocated memory.
 
Pointers provide the necessary support for C's dynamic allocation system.
 
The dynamic allocation system supports linked lists, binary trees and dynamically allocated arrays.
Dynamically Allocated Arrays and Pointers
 
Memory may be allocated using malloc() and operated on as if it were an array. Such &quotarrays"are known as dynamically allocated arrays . Since any pointer may be indexed as if it were a single-dimension array, the pointer returned by the malloc() function may be indexed in the normal way.
 
Multi-dimensional arrays, however, pose a problem. Since the dimensions have not been defined in the program, a trick must be used: The pointer is passed as a parameter to a function, which allows the function to define the dimensions of the parameter receiving the pointer, e.g.:
 
 
 
    p = malloc(40*sizeof(int));
    table(p);
    ...
    void table(int p[4][10]) // now the compiler has an array to work with
    {
      ...
    }
 
 
Essence of C
6 - FUNCTIONS
General Form, Scope Rules, Arguments, Calling Functions With Arrays, Returning Values and Pointers, Recursion
 
The General Form of a Function
 
The general form of a function is:
 
    type_specifier function_name(parameter list)
    {
     body of function;
    }
 
where type_specifier specifies the type of value that the function's return statement returns and the parameter list is a comma-separated list of variable names and types which receive the values of the arguments passed by the call to the function.
 
Scope Rules of Functions
 
The scope rules of a language are the rules which govern whether a piece of code knows about, or has access to, another piece of code or data.
 
In C, a function's code cannot be accessed other than by a call to that function. The code and data defined within a function cannot interact with the code or data defined in another function because two functions have a different scope.
 
Function Arguments
 
If a function is to use arguments, variables (known as formal parameters) must be declared to accept the values of the arguments. The type of the arguments used to call the function must be compatible with the type of its parameters. (The use of function prototypes can help catch errors in this regard.)
 
Assignments may be made to formal parameters, and those parameters may be used in any valid C expression. Essentially, parameters are, and may be used like, local variables.
 
Functions may be passed arguments by call-by-value or call-by-reference.
 
Call-by-Value
 
The call-by-value method copies the value of an argument into the formal parameter of the function. Therefore, changes made by the function to the parameters have no effect on the variables used to call it.
 
Call-by-Reference
 
The call-by-reference method copies the address of an argument into the formal parameter. Inside the function, this address is used to access the argument used in the call. In this way, changes made to the parameter affect the variable used in the call to the function.
 
Calls-by-reference are achieved by passing a pointer as the argument. Of course, in this case, the parameters must be declared as pointer types. The following demonstrates this:
 
 
 
    void swap(int *x, int *y); // function prototype
 
    void main(void)
    {
      int x,y;
 
      x = 10;
      y = 20;
      swap(&x,&y) // addresses passed
    }
 
    void swap(int *x, int *y)
    {
      int temp;
 
      temp = *x;
      *x = *y;
      *y = temp;
    }
 
Calling Functions With Arrays
 
Generally, the C convention is the call-by-value. An exception is where arrays are passed as arguments.
 
When an array is passed to a function, only the address is passed, not the entire array. When a function is called with just the array name, a pointer to the array is passed. (In C, an array name without an index is a pointer to the first element.) This means that the parameter declaration must be of a compatible pointer type. There are three ways to declare a parameter which is to receive an array pointer:
 
    * As an array, for example:
 
void display (int num[10]);
 
      in which case the compiler automatically converts it to a pointer.
    * As an unsized array:
 
void display (int num[]);
 
      which is also converted to a pointer.
    * As a pointer:
 
void display (int *num);
 
      which is allowed because, in C, any pointer may be indexed with [] as if it were an array. (This is the most common method.)
 
On the other hand, an array element used as an argument is treated like any other simple variable, as shown in this code fragment:
 
 
 
    display(t[a]);
    ...
    void display(int num)
    {
      printf("%d", num;
    }
 
argc and argv - Arguments to main()
 
Information may be passed into the program from the command line using the two special built-in arguments argc and argv. The former holds the number of arguments and the latter is a pointer to an array of character pointers. The value in argc is always at least 1 because the program name counts as the first argument. An example of usage is as follows:
 
 
 
    void main(int argc, char *argv[]) {
    if(argc != 2)
    {
      printf("You forgot to type your namen");
      exit(1);
    }
 
    printf("Hello %s", argv[1]);
    }
 
The names argc and argv are traditional but arbitrary, and may be changed to anything the programmer prefers.
 
The return Statement
 
return causes an immediate exit from a function. It may also be used to return a value. All functions, except those of type void, return a value. (If no return statement is present, most compilers will cause a 0 to be returned.)
 
Returning Values
 
As long as a function is not declared as void, it may be used as an operand in any C expression, e.g.:
 
 
 
    x = power(y);
    if(max(x,y) > 100)
      printf("greater");
    for(ch = getchar();isdigit(ch); );
 
However, a function cannot be the target of an assignment.
 
The purpose of most functions is to either perform a computation and return a value, manipulate information and return a success-or-failure (true or false) value, or perform a strictly procedural routine which produces no value (eg, the exit() function).
 
Some functions which do not produce an interesting result return something anyway. For example, printf() returns the number of characters written, although it would be unusual to find a program which used this value. In other words, the returned value does not have to be used if it serves no purpose.
 
Functions That Return Non-Integer Values
 
Functions may be declared to return any valid C data type. If the return type is not specified, it automatically defaults to type int. If a program calls a function which, due to a programming error, returns a type different from that specified by the function, and if that call is made before the function is declared, the compiler will generate the wrong code for the function call. To prevent this, a special form of declaration statement is used at the top of the program to tell the compiler what value that function is returning.
 
The traditional method for such declaration has now been replaced by the ANSI C method of the function prototype. The traditional method takes the form:
 
 
 
    type_specifier function_name();
 
The ANSI function prototype, on the other hand, takes the form:
 
 
 
    type function_name(type param_name1, type param_name2, ...,);
 
the difference being that the ANSI form specifies the type of the arguments expected to be received by the function. This enables the compiler to identify any type mismatch between the calling arguments and the formal parameters.
 
void must be used inside the parentheses of function prototypes for functions which receive no arguments.
 
Returning Pointers
 
Functions that return pointers are handled just like any other type of function, e.g.:
 
 
 
    char * match(char c, char *s)
    {
       while(c != *s && *s)
         s++;
       return(s);
    }
 
Functions of type void
 
Declaring a function of type void prevents its use in expressions. A void function's prototype must be declared before it is called, otherwise the compiler will assume that it returns an integer and declare a type mismatch.
 
What does main() Return?
 
The ANSI standard states that main() returns an integer to the calling process (generally the operating system). Returning a value from main() is the same as calling exit() with the same value. main() may be declared as void if it does not return a value.
 
Recursion
 
C supports recursion. In other words, in C, a function may call itself.
 
Parameter Lists of Variable Length and Type
 
In C, a function may be specified as having a varying number of parameters. In this case the parameter declaration must be ended with three periods, as in:
 
 
 
    function(int a, int b, ...);
 
This form must also be used in the function's prototype.
 
There must always be at least one actual argument.
 
Efficiency
 
Where execution speed is critical, in-line code should be used instead of the relevant function. In-line code is simply the function's statements used without a call to the function. In-line code is faster because the call itself takes time to execute and because the passed arguments must be placed on the stack, which also takes time.
 
Libraries and Files
 
Functions may be left in the main program or they may be placed in libraries or separate files. Technically, a library differs from a separately compiled file of functions in that, when a routine from a library is linked with the main program, only the functions used by that program are linked. Most C compilers include instructions for creating a library.
 
Essence of C
4 - ARRAYS AND STRINGS
Single Dimension Arrays, Two- and Mutliple-Dimension Arrays, Strings, Arrays of Strings
 
An array is a collection of variables of the same type which are referenced by a common name. A specific element in an array is referenced by an index. The most common array in C is the string, which is simply an array of characters terminated by a null.
 
In C, arrays and pointers are closely related; a discussion of one usually refers to the other.
 
C has no bounds checking on arrays.
 
Single Dimension Arrays
 
The general form for declaring a single-dimension array is:
 
    type var_name[size];
 
In C, all arrays have zero as the index of their first element. Therefore a declaration of char p[10]; declares a ten-element array (p[0] through p[9]).
 
Generating a Pointer to an Array
 
A pointer to the first element in an array may be generated by simply specifying the array name, without any index. For example, given:
 
    int sample[10];
 
a pointer to the first element may be generated by simply using the name sample. For example, the following code fragment assigns p the address of the first element of sample:
 
    int *p;
    int sample[10];
 
    p = sample;
 
The address of the first element may also be specified using the & operator. For example, sample and &sample[0] produce the same result. The former is usually used.
 
Passing Single-Dimension Arrays to Functions
 
In C, an entire array cannot be passed as an argument to a function. However, a pointer to an array may be passed by specifying the array's name without an index. If a function receives a single dimension array, the formal parameter may be declared as either a pointer, a sized array, or an unsized array. Examples are:
 
    function(int *x)     // A pointer.
    function(int x[10]) // A sized array.
    function(int x[])    // An unsized array.
 
Strings
 
A string is actually an array of characters. Because strings are terminated by a null (''), character arrays must be declared with one extra element (to hold the null).
 
Although C does not have a string data type, it allows string constants. For example, "hello there" is a string constant.
 
C supports a wide range of string manipulation functions, including:
 
Function           Description
strcpy(s1,s2)    Copies s2 into s1.
strcat(s1,s2)     Concatenates s2 to s1.
strlen(s1)          Returns the length of s1.
strcmp(s1,s2)  Returns 0 (false) if s1 and s2 are the same.
Returns less than 0 if s1&lts2
Returns greater than 0 if s1>s2
strchr(s1,ch)     Returns pointer to first occurrence ch in s1.
strstr(s1,s2)      Returns pointer to first occurrence s2 in s1.
 
Since strcmp() returns false if the strings are equal, it is best to use the ! operator to reverse the condition if the test is for equality.
 
Two-Dimensional Arrays
 
In C, a two-dimensional array is declared as shown in the following example:
 
    int d[10][20];
 
Two-dimensional arrays are stored in a row-column matrix. The first index indicates the row. The row index can be thought of as a &quotpointer"to the correct row.
 
When a two-dimensional array is used as an argument to a function, only a pointer to the first element is passed. However, the receiving function must define at least the length of the second dimension, e.g.:
 
    function(int x[][20]
 
Arrays of Strings
 
Arrays of strings are created using a two-dimensional array. The left index determines the number of strings. Each string is accessed using only the left index (eg, gets(array[2] accesses the third string).
 
Multi-Dimensional Arrays
 
C allows arrays of more than two dimensions, the exact limit depending on the individual compiler.
 
Indexing Pointers
 
In C, pointers and arrays are closely related. As previously stated, an array name without an index is a pointer to the first element. For example, given the array char my_array[10];, my_array and &my_array[0] are identical.
 
Conversely, any pointer variable may be indexed as if it were declared as an array. For example, in this program fragment:
 
    int *p, i[10];
 
    p = i;
    p[5] = 100; // assignment using index
    (p+5) = 100 // assignment using pointer arithmetic
 
both assignments achieve the same thing.
 
Pointers are sometimes used to access arrays because pointer arithmetic is faster than array indexing.
 
In a sense, a two-dimensional array is like an array of pointers that point to arrays of rows. Therefore, using a separate pointer variable is one easy way to access elements. For example, the following prints the contents of the specified row for the global array num:
 
    int num[10][10];
    ...
    void print_row(int j)
    {
      int *p, t;
 
      p = &num[j][0]; // get address of first element in row j
      for(t=0;t<10;++t)
        printf("%d ", *(p+t));
    }
 
Array Initialization
 
Arrays may be initialized at the time of declaration. The following example initializes a ten-element integer array:
 
    int i[10] = { 1,2,3,4,5,6,7,8,9,10 };
 
Character arrays which hold strings allow a shorthand initialization, e.g.:
 
    char str[9] = "I like C";
 
which is the same as:
 
    char str[9] = { 'I',' ','l','i','k','e',' ','C','' };
 
When the string constant method is used, the compiler automatically supplies the null terminator.
 
Multi-dimensional arrays are initialized in the same way as single-dimension arrays, e.g.:
 
    int sgrs[6][2] =
    {
      1,1,
      2,4,
      3,9,
      4,16,
      5,25
      6,36
    };
 
Unsized Array Initializations
 
If unsized arrays are declared, the C compiler automatically creates an array big enough to hold all the initializers. This is called an unsized array. Example declaration/initializations are as follows:
 
    char e1[] = "read errorn";
    char e2[] = "write errorn";
 
    int sgrs[][2] =
    {
      1,1,
      2,4,
      3,9
      4,16,
    };
 
 
 
 
 
Essence of C
7 - CUSTOM DATA TYPES
Structures, Bit-Fields, Unions, Enumerations, typedef
 
C allows the programmer to create custom data types in five different ways. These are:
 
    * The structure, which is a collection of variables under one name.
    * The bit-field, a variation of the structure which allows easy access to the bits of a word.
    * The union, which enables the same piece of memory to be defined as two or more types of variables.
    * The enumeration, which is a list of symbols.
    * Types created with typedef, which defines a new name for an existing type.
 
Structures
 
A structure is a collection of variables referenced under one name, providing a convenient means of keeping related information together.
 
Definition
 
A structure definition forms a &quottemplate"which may be used to create structure variables. The variables which make up a structure are called structure elements.
 
In the following, the C keyword struct tells the compiler that a structure template is being defined:
 
     struct addr
     {
       char name[30];
       char street[40];
       int postcode;
    };
 
In this example, addr is known as the structure tag. Note that a structure definition is actually a statement; hence it is terminated by a semi-colon. Note also that only the form of the data has been defined at this stage and that no variable has yet been declared.
 
Declaration
 
An example of a structure variable declaration of type addr is:
 
 
 
     struct addr addr_info;
 
Variables may also be declared as the structure is defined, as in:
 
     struct addr
     {
       char name[30];
       char street[40];
       int postcode;
     } addr_info, binfo, cinfo;
 
If only one variable is needed, the structure tag is not needed, e.g.:
 
     struct
    {
      char name[30];
      char street[40];
      int postcode;
    } addr_info;
 
Referencing Structure Elements
 
Individual elements of a structure are referenced using the dot operator, e.g.:
 
     addr_info.postcode = 1234;
     printf("%d",addr_info.postcode);
 
Structure Assignments
 
ANSI C compilers allow the information in one structure to be assigned to another structure, as in:
 
     binfo=addr_info;
 
Arrays of Structures
 
The following example declares a 100-element array of type addr:
 
     struct addr addr_arr[100];
 
in which the postcode element of structure 3 would be accessed by:
 
     printf("%d", addr_info[2].postcode);
 
Passing Structures to Functions
 
When an element of a non-global structure is to be passed to a function, the value of that element is passed (unless that element is complex, such as an array of characters). For example, given:
 
     struct fred
     {
       char x;
       int y;
       char z[10];
     } mike;
 
each element would be passed like this:
 
    funct(mike.x);            // passes character value of x
    funct(mike.y);            // passes integer value of y
    funct(mike.s);            // passes address of string
    funct(mike.s[2]);         // passes character val of s[2]
 
If the address of the element is required to be passed, the & operator is placed before the structure name. In the above example, this would apply except in funct(mike.s);.
 
Passing Entire Structures to Functions
 
When a structure is used as an argument to a function, the entire structure is passed using the standard call-by-value method. Of course, this means that changes made to the contents of the structure inside the function do not affect the structure used as the argument.
 
Declaring Structure Pointers
 
Assuming the previously defined structure addr, the following declares addr_pointer as a pointer to data of that type:
 
    struct addr *addr_pointer;
 
Using Structure Pointers
 
Structure pointers may be used to generate a call-by-reference to a function and to create linked lists and other dynamic data structures. Calls-by-reference should be used for all but the simplest structures so as to avoid overheads occasioned by the pushing and popping of all the structure elements onto and off the stack.
 
To access the elements of a structure using a pointer, the -> operator is used, as in:
 
    ptr->postcode
 
where ptr has been declared as a pointer to the type of structure and assigned the address of a variable of that type, and postcode is a structure element within that variable.
 
Arrays and Structures Within Structures
 
Structure elements may be arrays and structures. When a structure is an element of another structure, it is called a nested structure.
 
Bit-Fields
 
Preamble. Unlike most other languages, C has a built-in method for accessing a single bit within a byte. This can be useful because:
 
    * If memory is tight, several Boolean (true/false) variables can be stored in one byte, saving memory.
    * Certain devices transmit information encoded into bits within one byte.
    * Certain encryption routines need to access individual bits within a byte.
 
Tasks involving the manipulation of bits may, of course, be performed using C's bitwise operators. However, the bit-field provides a means of adding more structure and efficiency to the coding.
 
Bit-Fields - A Type of Structure
 
To access bits using bit-fields, C uses a method based on the structure. In fact, a bit-field is simply a special type of structure element which defines how long, in bits, the field is to be. The general form of a bit-field definition is:
 
    struct tag
    {
      type name1: length;
      type name2: length;
      type name3: length;
    } variable_list;
 
A bit-field must be declared as either int, unsigned, or signed. Bit-fields of length 1 should be declared as unsigned because a single bit cannot have a sign.
 
An Example Application
 
Bit-fields are frequently used when analyzing input from a hardware device. For example, the status port of a serial communications device might return a status byte like this:
 
Bit
           
 
Meaning When Set
0          Change in clear-to-send line.
1          Change in data-set-ready.
2          Trailing edge detected.
3          Change in receive line.
4          Clear-to-send.
5          Data-set-ready.
6          Telephone ringing.
7          Received signal.
 
Defining the Bit-Field. The foregoing can be represented in a status byte using the following bit-field definition/declaration:
 
    struct status_type
    {
      unsigned delta_cts: 1;
      unsigned delta_dsr: 1;
      unsigned tr_edge:   1;
      unsigned delta_rec: 1;
      unsigned cts:       1;
      unsigned dsr:       1;
      unsigned ring:      1;
      unsigned rec_line: 1;
    } status;
 
Using this bit-field, the following routine would enable a program to determine whether it can send or receive data:
 
    status = get_port_status;
 
    if(status.cts)
      printf("Clear to send");
    if(status.dsr)
      printf("Data set ready);
 
Referencing Bit-Field Elements
 
Values are assigned to a bit-field using the usual method for assigning values to structure elements, e.g.:
 
    status.ring = 0;
 
As with structures, if an element is referenced through a pointer, the -> operator is used in lieu of the dot operator.
 
Variations in Definition
 
All bit-fields need not necessarily be named, which allows unused ones to be bypassed. For example, if, in the above example, access had only been required to cts and dsr, status_type could have been declared like this:
 
    struct status_type
    {
      unsigned:     4;
      unsigned cts: 1;
      unsigned dsr: 1;
    } status;
 
Limitations
 
Bit-field variables have certain limitations. For example:
 
    * The address of a bit-field variable cannot be taken.
    * Bit-field variables cannot be arrayed.
    * Integer boundaries cannot be overlapped.
    * There is no certainty, from machine to machine, as to whether the fields will run from right to left or from left to right. In other words, any code using bit-fields may have some machine dependencies.
 
Mixing Normal and Bit-Field Structure Elements
 
Normal and bit-field structure elements may be mixed, as in:
 
    struct emp
    {
      struct addr address;
      float pay;
      unsigned lay-off: 1; // lay-off or active
      unsigned hourly: 1; // hourly pay or wage
      unsigned deducts: 3; // tax deductions
     }
 
which demonstrates the use of only one byte to store information which would otherwise require three bytes.
 
Unions
 
A union is a memory location which is shared by two or more different variables, generally of different types, at different times. The general form of a union definition is:
 
    union tag
    {
      type variable_name;
      type variable_name;
      type variable_name;
     .
     .
    } union_variables;
 
An example definition is as follows:
 
    union u_type
    {
      int i;
      char ch;
    };
 
Declaration options are as for structures, ie, variable names may be placed at the end of the definition or a separate declaration statement may be used.
 
In the example shown, both the integer i and the character ch share the same memory location, even though ch only requires the first of the bytes required by i.
 
Accessing Union Elements
 
Union elements are accessed using the same methods used for accessing structure elements.
 
Usage
 
The union aids in the production of machine-independent code because the compiler keeps track of the actual sizes of the variables which make up the union.
 
Unions are frequently used when type conversions are needed because the data held in a union can be referred to in different ways.
 
Enumerations
 
An enumeration is a set of named integer constants which specify all the legal values a variable of that type may have. Enumerations are common in everyday life. For example, an enumeration of the coins in a currency might be:
 
    10 cents, 25 cents, 50 cents, dollar
 
Definition and Declaration
 
Enumerations are defined much like structures. An example definition is as follows:
 
    enum coin { ten_cent, quart_doll, half_doll, dollar };
 
An example declaration is:
 
    enum coin money;
 
Given this definition and declaration, the following statements are valid:
 
    money = quart_doll;
 
    if(money == quart_doll)
     printf("is 25 centsn");
 
In an enumeration, each symbol stands for an integer value. For example, using the above definition and declaration:
 
    printf("%d %d", ten_cent, dollar);
 
displays 0 3 on the screen.
 
Initialization
 
The symbols in an enumeration may be initialized, as in the following example:
 
    enum coin { ten_cent, quart_doll, half_doll=100, dollar };
 
which would place these values in the symbols:
 
    ten_cent   0
    quart_doll 1
    half_doll 100
    dollar     101
 
To avoid the rather tedious coding arising from the fact that symbols are integers and not strings, an array of strings may be declared for access by the enumeration, e.g.:
 
    char name[] =
    {
      "10 cents",
      "25 cents",
      "50 cents",
      "dollar"
    }
 
    money = quart_doll;
    printf("%s", name[money]);
 
Note that this only works if no symbol is initialized, the reason being that the string array must be indexed starting at 0.
 
typedef
 
typedef allows a new data type to be explicitly defined. Note that it does not actually create a new data class, but simply defines a new name for an existing type. This process helps in making machine-dependent code more portable, since only the typedef statements need be changed. It can also aid in self-documenting a program by allowing the use of more descriptive names for the standard data types.
 
For example, a new name for float could be created as follows:
 
    typedef float balance;
 
which would allow a new float variable to be created by:
 
Essence of C
8 - CONSOLE INPUT/OUTPUT
Reading and Writing Characters and Strings, Formatted Console Input/Output
 
Introduction
 
C is virtually unique as a language in that it has no keywords for input/output (I/O). Instead, I/O is accomplished through library functions.
 
There are two types of I/O in C, viz, console I/O and file I/O. Technically, there is little distinction between the two, although they are, conceptually, quite different worlds.
 
The standard C console I/O functions perform only TTY-based output; however, most compilers include in their libraries machine-specific screen control and graphics functions.
 
It should be noted that, although the following pertains to input from the keyboard and output to the screen, the actual source and target of C's I/O functions are the standard input and standard output of the system, which means that this input and output may be re-directed to other devices.
 
Reading and Writing Characters
 
The following functions read characters from the keyboard and write characters to the screen:
 
Function           Operation
getchar()          
 
Reads a character from the keyboard; waits for carriage return. Returns an integer, in which the low-order byte contains the character. Any key, including RETURN, TAB and ESC may be returned by getchar().
 
Note: Because it waits for a carriage return, getchar() is not useful in an interactive environment (except in the case of some compilers which actually implement getchar() as an interactive function, which is permitted by the ANSI standard). The ANSI standard does not, in fact, define any function guaranteed to provide interactive input, but many C compilers include alternative keyboard input functions which achieve this.
getch() Waits for a keypress, after which it returns immediately. Reads the character without an echo to the screen. (One of the common alternatives to getchar(). Not defined by ANSI.)
getche()            Same as getch(), but echoes the character.
putchar()          Writes a character to the screen. Declared as using an integer parameter; however, only the low-order byte is output to the screen. Returns the character written, or EOF (-1) if an error occurs.
 
Reading and Writing Strings
 
The following functions read and output strings:
 
Function           Operation
gets()    Reads a string of characters and places them at the address pointed to by its character pointer argument. When RETURN is entered, a null terminator is placed at the end of the string and the function returns. Typing errors may be corrected with the BACKSPACE key.
puts()  Writes its string argument to the screen, followed by a newline. Recognizes the same "backslash" codes as printf() (eg, t for TAB). Cannot output numbers, but is faster than printf() in outputting strings. Returns EOF if an error occurs.
 
Formatted Console I/O
 
The functions printf() and scanf() read and write data in various formats specified by the programmer. Both functions can operate on any of the built-in data types, including characters, strings and numbers.
 
printf()
 
The prototype for printf() is:
 
    int printf(char *control_string,argument_list);
 
Where control_string consists of two types of items, namely, characters which will be printed to the screen and format specifiers which control how the subsequent arguments are displayed.
 
Format Specifiers
 
The various format specifiers are as follows:
 
Specifier           Description
%c       Character.
%d       Signed decimal integer.
%i        Signed decimal integer.
%e       Scientific notation (lowercase e).
%E       Scientific notation (uppercase E).
%f        Decimal floating point.
%g       Uses %e or %f, whichever is shorter.
%G      Uses %E or %F, whichever is shorter.
%o       Unsigned octal.
%s       String of characters.
%u       Unsigned decimal integers.
%x       Unsigned hexadecimal (lowercase letters).
%X      Unsigned hexadecimal (uppercase letters).
%p       Pointer.
%n       The argument is an integer pointer into which the number of characters written so far is placed. Enables a program to perform dynamic formatting.
%%      Prints a %.
 
The %n format specifier is different from the other specifiers. As an example of usage, this code fragment:
 
    int count;
 
    printf("this%nis a testn", &count);
    printf("%d", count);
 
would cause this is a test followed by 4 to be displayed.
 
Format Modifiers
 
Many format specifiers may take format modifiers, which slightly alter their meaning. These modifiers include the following:
 
    * Minimum Field Width Specifier. The minimum field width specifier pads the output with spaces to ensure that it reaches a certain minimum width. This code:
 
item=10.12304;
 printf("%fn", item); printf("%10fn", item); printf("%012fn",
 item);
 
      produces this output:
 
10.123040 10.123040 00010.123040
 
 
      Note that, in the third example, a zero has been used for the padding.
 
      The minimum field width specifier is most commonly used to produce tables of right-justified numbers.
    * Precision Specifier. The precision specifier follows the minimum field width specifier (if there is one). It consists of a period followed by an integer. Its exact meaning depends on the type of data it is applied to, e.g.:
          o Floating Point Types. When applied to floating-point data, it determines the number of decimal places to be displayed. For example, %10.4f displays a number at least 10 characters wide with 4 decimal places.
          o Integer Types. When applied to integer types, it determines the minimum number of digits which will appear for each number. Leading zeros are added to achieve the required number of digits.
          o Strings. When applied to strings, it specifies the maximum field length. For example, %5.7s displays a string at least 5, and not exceeding 7, characters long. If the string is longer than the maximum field width, the end characters will be truncated.
 
      As an example, this code:
 
printf("%.4fn",
 123.1234567); printf("%12.4fn", 123.1234567); printf("%8.10dn",
 1234); printf("%10.8dn", 1234); printf("%10.15sn",
 "This is a simple test"); printf("%9.6sn", "Testing");
 
 
      produces this output:
 
123.1235 123.1235 0000001234 00001234
 This is a simpl Testin
 
Left Justification (-)
 
By default, output is right-justified. That is, if the field width is larger than the data printed, the data will be placed at the right edge. Left justification may be forced by using a minus sign after the %. For example, %-10.2f left justifies a floating point number in a ten-character field.
 
The l, h and L Modifiers
 
The l and h modifiers may prefix the d, i, o, u, and x type specifiers. l tells printf() that a long data type follows. h tells printf() to display a short int.
 
The L modifier may also prefix the floating point specifiers e, f, and g and indicates that a long double follows.
 
The # Modifier
 
Preceding g, f, or e specifiers with a # ensures that there will be a decimal point even if there are no decimal digits.
 
Preceding the x specifier with a # ensures that the hexadecimal number will be printed with a 0x prefix.
 
The * Modifier
 
The minimum field width and precision specifiers are usually constants; however, they may also be provided by arguments to printf(). To achieve this, * is used as a placeholder. For example, in:
 
    printf("%*.*f", 10, 4, 1234.34);
 
the minimum field width is 10, the precision is 4 and the value to be displayed is 1234.34.
 
scanf()
 
scanf() is the general purpose console input function. It can read in all of the built-in data types and automatically convert numbers into the proper internal format. The prototype is:
 
    int scanf(char *control_string, argument_list);
 
scanf() returns the number of data items successfully assigned a value. If an error occurs, EOF is returned
 
Format Specifiers
 
The input format specifiers tell scanf() what type of data is to be read next. The codes are as follows:
 
Specifier           Description
%c       Read a single character.
%d       Read a decimal integer.
%i        Read a decimal integer.
%e       Read a floating-point number.
%f        Read a floating-point number.
%g       Read a floating-point number.
%o       Read an octal number.
%s       Read a string.
%x       Read a hexadecimal number.
%p       Read a pointer.
%n       Receive an integer value equal to the number of characters read so far.
%u       Read an unsigned integer.
%[]      Scan for a set of characters.
 
Reading Strings
 
%s causes scanf() to read characters until it encounters a white-space character (RETURN, TAB or space). The characters read are placed in a character array pointed to be the corresponding argument, and null-terminated.
 
Unlike gets(), which reads a string until RETURN is typed, scanf() reads a string until the first white space is encountered.
 
The %n Specifier
 
The %n specifier instructs scanf() to assign the number of characters read at the point at which the %n was encountered to the variable pointed to by the corresponding argument.
 
Using a Scanset
 
The ANSI standard added the new scanset feature. A scanset defines a set of characters which may be read and assigned to the corresponding character array.
 
A scanset is defined by placing the characters inside square brackets prefixed with a %, as in the following example:
 
     %["XYZ"]
 
scanf() will then continue to read characters and continue to put them into the array until it encounters a character not in the scanset. For example, given the following code:
 
     scanf(%d%[abcdefg]%s", &i, str, str2);
     printf(%d %s %s, i, str, str2);
 
entering 123abcdtye followed by ENTER would display:
 
     123 abcd tye
 
because the t is not part of the scanset, causing it and the remaining characters to be put into str2.
 
If the first character in the set is a ^, scanf() will accept any character not defined by the scanset. A range may be specified using a hyphen. Scansets are case sensitive.
 
The Need For Addresses
 
All the variables used to receive values through scanf() must be passed by their addresses, which means that all arguments must be pointers to the variables used as arguments. This is, of course, C's way of creating a call-by-reference, which is a way of allowing a function to alter the contents of its calling argument. This is illustrated in the following example:
 
     scanf("%d", &count);
     scanf("%s", str);
 
The second line in the above code works because an array name, without an index, is the address of the first element of the array. Hence the & operator is not required.
 
Format Modifiers
 
An integer, placed between the % and the format, limits the number of characters read for that field. (Any characters in the input stream outside this limit will be placed in the relevant variable at the next scanf() call.)
 
l placed in front of f, e and g causes scanf() to assign the data to a double. L tells scanf() that the variable receiving the data is a long double.
 
Suppressing Input
 
scanf() may be told to read a field but not assign it to any variable by preceding that field's format code with a *. For example, given:
 
    scanf("%d*c%d", &x, &y);
 
the coordinate pair 10,10 could be entered. The comma would be read but not assigned to anything.
 
Assignment suppression is particularly useful when part of what is input needs to be suppressed.
 
    balance overdue;
 
Essence of C
10 - THE C PREPROCESSOR
 
The C Preprocessor
 
As defined by the ANSI standard, the C preprocessor contains the following directives:
 
#if #ifdef #ifndef #else #elif #include #define #undef #line #error #pragma
 
#define
 
#define defines an identifier (the macro name) and a string (the macro substitution) which will be substituted for the identifier each time the identifier is encountered in the source file.
 
Once a macro name has been defined, it may be used as part of the definition of other macro names.
 
If the string is longer than one line, it may be continued by placing a backslash on the end of the first line.
 
By convention, C programmers use uppercase for defined identifiers. Example macro #defines are:
 
     #define TRUE 1
     #define FALSE 0
 
The macro name may have arguments, in which case every time the macro name is encountered, the arguments associated with it are replaced by the actual arguments found in the program, as in:
 
     #define ABS(a) (a)<0 ? -(a) : (a)
     ...
     printf("abs of -1 and 1: %d %d", ABS(-1), ABS(1));
 
Such macro substitutions in place of real functions increase the speed of the code at the price of increased program size.
 
#error
 
#error forces the compiler to stop compilation. It is used primarily for debugging. The general form is:
 
     #error error_message
 
When the directive is encountered, the error message is displayed, possibly along with other information (depending on the compiler).
 
#include
 
#include instructs the compiler to read another source file, which must be included between double quotes or angle brackets. Examples are:
 
     #include "stdio.h"
     #include <stdio.h>
 
which both instruct the compiler to read and compile the named header file.
 
If a file name is enclosed in angle brackets, the file is searched for as specified by the creator of the compiler. If the name is enclosed in double quotes, the file is searched for in an implementation-defined manner, which generally means searching the current directory. (If the file is not found, the search is repeated as if the name had been enclosed in angle brackets.)
 
Conditional Compilation - #if, #else, #elif, and #endif
 
Several directives control the selective compilation of portions of the program code, viz, #if, #else, #elif, and #endif.
 
The general form of #if is:
 
     #if constant_expression
     statement sequence
     #endif
 
#else works much like the C keyword else. #elif means "else if" and establishes an if-else-if compilation chain.
 
Amongst other things, #if provides an alternative method of "commenting out" code. For example, in
 
     #if 0
     printf("#d",total);
     #endif
 
the compiler will ignore printf("#d",total);.
 
#ifdef and #ifndef
 
#ifdef means "if defined", and is terminated by an #endif. #indef means "if not defined".
 
#undef
 
#undef removes a previously defined definition.
 
#line
 
#line changes the contents of __LINE__ (which contains the line number of the currently compiled code) and __FILE__ (which is a string which contains the name of the source file being compiled), both of which are predefined identifiers in the compiler.
 
#pragma
 
The #pragma directive is an implementation-defined directive which allows various instructions to be given to the compiler.
 
The # and ## Preprocessor Operators
 
The # and ## preprocessor operators are used when using a macro #define.
 
The # operator turns the argument it precedes into a quoted string. For example, given:
 
     #define mkstr(s) # s
 
the preprocessor turns the line
 
     printf(mkstr(I like C);
 
into
 
     printf("I like C");
 
The ## operator concatenates two tokens. For example, given:
 
     #define concat(a, b) a ## b
 
     int xy=10;
     printf("%d",concat(x, y);
 
the preprocessor turns the last line into:
 
     printf("%d", xy);
 
Predefined Macro Names
 
The ANSI standard specifies five built-in predefined macro names. These are:
 
     __LINE__ __FILE__ __DATE__ __TIME__ __STDC__
 
__LINE__ and __FILE__ have already been discussed.
 
__DATE__ and __TIME__ contain strings of the form month/date/year and hour/minute/second which represent the date and time of compilation.
 
__STDC__ contains the decimal constant 1, which means that the implementation conforms to the standard. If it contains any other number, the implementation varies from the standard.
 

Site Maintained by
Saravanan.R.R.
NithinRaj.P

For Job Searching
www.naukri.com
www.freshersworld.com
www.jobsearch.monsterindia.com
www.recruit.net
www.timesjobs.com
www.jobsearchworld.com
www.placementindia.com
www.bestjobsindia.in
www.jobsahead.com
www.jobsearch.co.in
www.jobsearchinformation.com
www.jobconsultancy.com
www.marketingcrossing.com
www.mobile.monsterindia.com
www.hinduonnet.com

Tutorials Searching
www.howstuffworks.com
www.tutor.com
www.en.wikipedia.org
www.mathguru.com
www.knowledgeonlineservices.com
www.mygretutor.com

English Tutor Searching
www.englishgrammartutor.com
www.theenglishtutor.com
www.learnenglish.de
www.tolearnenglish.com
www.englishclub.com
www.english-at-home.com
www.learn-english.co.il
www.learnenglish.be

For Entrance Exam Details Searching
www.winentrance.com
www.entranceexamindia.com
www.studyplaces.com
www.entranceexam.info
www.indiastudychannel.com
www.edudiary.com
www.successcds.net

Today, there have been 6 visitors (33 hits) on this page!
=> Do you also want a homepage for free? Then click here! <=