Friday, 2 May 2014

Declarations and Types


  1. Storage classes
  2. Type specifiers / Data Types
  3. Type qualifiers
  4. Declarators and variable declarations
  5. Typedef declarations

1.       C Storage Classes

The "storage class" of a variable determines whether the item has a "global" or "local" lifetime. C calls these two lifetimes "static" and "automatic." An item with a global lifetime exists and has a value throughout the execution of the program. All functions have global lifetimes.

Automatic variables, or variables with local lifetimes, are allocated new storage each time execution control passes to the block in which they are defined. When execution returns, the variables no longer have meaningful values.

C provides the following storage-class specifiers:
                                                1.1 auto
                                                1.2 register
                                                1.3 static
                                                1.4 extern
                                               
Items declared with the auto or register specifier have local lifetimes. Items declared with the static or externspecifier have global lifetimes.

                           1.1            Auto
A variable declared inside a function without any storage class specification, is by default an automatic variable. They are created when a function is called and are destroyed automactically when the function exits. Automatic variables can also be called local variables because they are local to function. By default assigned garbage value by compiler:

Void main()
{
      int detail;
      Or
      Auto int detail; //Both are same
}

                           1.2            Register
Register variable informs the compiler to store the variable in register instead of memory. Register variable has faster access than normal variable. Frequently used variables are kept in register. Only few variables can be placed inside register. We can never get address of variables stored in register.

register int number;

                           1.3            Static
A static variable tells the compiler to persist the variable until the end of program. Instead of creating and destroying a variable every time when it comes into and goes out of scope, static is initialized only once and remains into existence till end of program. A static variable can either be internal or external depending upon the place of declaration. Scope of internal static variable remains inside the functional in which it is defined. External static variable remain restricted to scope of file in which they are declared.
They are assigned 0(zero) as default value by the complier.

Example 1:

void test():
main()
{
      test() ;
      test() ;
      test() ;
}
void test()
{
      static int a=0;
      a = a+1;
      printf (“%d\t”,a);
}

Output:
1     2     3



Example 2:

int GLOBAL ;

int function( void )
{
    int LOCAL ;
    static int *lp = &LOCAL;   /* Illegal initialization */
    static int *gp = &GLOBAL;  /* Legal initialization   */
    register int *rp = &LOCAL; /* Legal initialization   */

}

In C, if an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a NULL pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.

                           1.4            extern
The extern keyword is used before a variable to inform the compiler that this variable is declared somewhat else. The extern declaration does not allocate storage for variables.


2.       C Type Specifiers / Data Types
Data Type specifies how we enter data into our programs and what type of data we enter.
Primary Data types: These are fundamental data types in C namely integer(int), floating(float) and void.
Derived Data types / Extended Data types: Derived data types are like arrays, structures & Pointers.



Void
The void type specifies that no value is available. It is used in three kinds of situations:
S.N.
Types and Description
1
Function returns as void
There are various functions in C which do not return value or you can say they return void. A function with no return value has the return type as void. For example void exit (int status);
2
Function arguments as void
There are various functions in C which do not accept any parameter. A function with no parameter can accept as a void. For example, int rand(void);
3
Pointers to void 
A pointer of type void * represents the address of an object, but not its type. For example a memory allocation function void *malloc( size_t size ); returns a pointer to void which can be casted to any data type.

Void Pointers: Suppose we have declare integer pointer, character pointer and float pointer then we need to declare 3 pointer variables. Instead of declaring different types of pointer variable it is feasible to declare single pointer variable which can act as integer pointer, character pointer.

void *ptr;
char cnum;
int inum;

ptr = &cnum; //ptr has address of character data
ptr = &inum; //ptr has address of integer data
ptr = &fnum; //ptr has address of float data

Void pointer declaration is shown above. When have declared 3 variables of integer, character & float type. When we assign address of integer to void pointer, pointer will become Integer pointer. When we assign address off Character Data type pointer it will become Character Pointer. Similarly we can assign address of any data type to the void pointer. It is capable of storing address of any data type.

Integer type:
Integers are used to store whole numbers.



Floating type:
Floating types are used to store real numbers.

Character type:
Character types are used to store characters value.



3.       Type Qualifier: The keywords which are used to modify the properties of a variable are called type qualifiers.
Standard C language recognizes the following two qualifiers:
  • const
  • volatile
The const qualifier is used to tell C that the variable value cannot change after initialization.
const float pi=3.14159;
Now pi cannot be changed at a later time within the program.
The volatile qualifier declares a data type that can have its value changed in ways outside the control or detection of the compiler (such as a variable updated by the system clock or by another program). This prevents the compiler from optimizing code referring to the object by storing the object's value in a register and re-reading it from there, rather than from memory, where it may have changed.


4.       Declarators and variable declarations



   4.1            Simple Variables:
The declaration of a simple variable, the simplest form of a direct declarator, specifies the variable's name and type. It also specifies the variable's storage class and data type.
Storage classes or types (or both) are required on variable declarations. Untyped variables (such as var;) generate warnings.
You can use a list of identifiers separated by commas (,) to specify several variables in the same declaration. All variables defined in the declaration have the same base type. For example:
int x, y;        /* Declares two simple variables of type int */
int const z = 1; /* Declares a constant value of type int */

The variables x and y can hold any value in the set defined by the int type for a particular implementation. The simple object z is initialized to the value 1 and is not modifiable.

   4.2            Arrays
An "array declaration" names the array and specifies the type of its elements. It is possible to make arrays whose elements are basic types. Thus we can make an array of 10 integers with the declaration.
int x[10];
The square brackets mean subscripting; parentheses are used only for function references. Array indexes begin at zero, so the elements of x are:
Thus Array are special type of variables which can be used to store multiple values of same data type. Those values are stored and accessed using subscript or index.
Arrays occupy consecutive memory slots in the computer's memory.
x[0], x[1], x[2], ..., x[9]
int array [8] = {2, 4, 6, 8, 10, 12, 14, 16};
Two Dimensional Arrays
C language supports multidimensional arrays. The simplest form of the multidimensional array in the two dimensional array. Two dimensional array is declared as follows,
type array-name[row-size][column-size]
Example:
int a[3][4];




a[0][0]  a[0][1]  a[0][2]  a[0][3]




a[1][0]  a[1][1]  a[1][2]  a[1][3]




a[2][0]  a[2][1]  a[2][2]  a[2][3]

   4.3            Pointers
pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address. The general form of a pointer variable declaration is:
type *var-name;
Here, type is the pointer's base type; it must be a valid C data type and var-name is the name of the pointer variable.
int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

   4.4            Enumeration
An enumeration consists of a set of named integer constants. An enumeration type declaration gives the name of the (optional) enumeration tag and defines the set of named integer identifiers (called the "enumeration set," "enumerator constants," "enumerators," or "members"). A variable with enumeration type stores one of the values of the enumeration set defined by that type.
enum identifier { enumerator-list }
Enumerations provide an alternative to the #define preprocessor directive with the advantages that the values can be generated for you and obey normal scoping rules.
The following rules apply to the members of an enumeration set:
  • An enumeration set can contain duplicate constant values. For example, you could associate the value 0 with two different identifiers, perhaps named null and zero, in the same set.
  • The identifiers in the enumeration list must be distinct from other identifiers in the same scope with the same visibility, including ordinary variable names and identifiers in other enumeration lists.
  • Enumeration tags obey the normal scoping rules. They must be distinct from other enumeration, structure, and union tags with the same visibility.
Examples:
enum DAY            /* Defines an enumeration type    */
{
    saturday,       /* Names day and declares a       */
    sunday = 0,     /* variable named workday with    */
    monday,         /* that type                      */
    tuesday,
    wednesday,      /* wednesday is associated with 3 */
    thursday,
    friday
} workday;
The value 0 is associated with saturday by default. The identifier sunday is explicitly set to 0. The remaining identifiers are given the values 1 through 5 by default.


   4.5            Structures
Structure is user defined data type available in C programming, which allows you to combine data items of different kinds.

Defining a Structure
To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than one member for your program. The format of the struct statement is this:

struct [structure tag]
{
   member definition;
   member definition;
   ...
   member definition;
} [one or more structure variables];

The structure tag is optional and each member definition is a normal variable definition, such as int i; or float f; or any other valid variable definition. At the end of the structure's definition, before the final semicolon, you can specify one or more structure variables but it is optional. Here is the way you would declare the Book structure:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book; 

Accessing Structure Members
To access any member of a structure, we use the member access operator (.). The member access operator is coded as a period between the structure variable name and the structure member that we wish to access. You would use struct keyword to define variables of structure type. Following is the example to explain usage of structure:

#include <stdio.h>
#include <string.h>

struct Books
{
   char title[50];
   char author[50];
   char subject[100];
   int   book_id;
};

int main( )
{
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */

   /* book 1 specification */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali");
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* book 2 specification */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;

   /* print Book1 info */
   printf( "Book 1 title : %s\n", Book1.title);
   printf( "Book 1 author : %s\n", Book1.author);
   printf( "Book 1 subject : %s\n", Book1.subject);
   printf( "Book 1 book_id : %d\n", Book1.book_id);

   /* print Book2 info */
   printf( "Book 2 title : %s\n", Book2.title);
   printf( "Book 2 author : %s\n", Book2.author);
   printf( "Book 2 subject : %s\n", Book2.subject);
   printf( "Book 2 book_id : %d\n", Book2.book_id);

   return 0;
}

When the above code is compiled and executed, it produces the following result:

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

   4.6            Unions
union is a special data type available in C that enables you to store different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time. Unions provide an efficient way of using the same memory location for multi-purpose.
                Defining a Union
To define a union, you must use the union statement. The union statement defines a new data type, with more than one member for your program. The format of the union statement is as follows:
union [union tag]
{
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables]; 

The union tag is optional and each member definition is a normal variable definition, such as int i; or float f; or any other valid variable definition. At the end of the union's definition, before the final semicolon, you can specify one or more union variables but it is optional. Here is the way you would define a union type named Data which has the three members i, f, and str:

union Data
{
   int i;
   float f;
   char  str[20];
} data

Now, a variable of Data type can store an integer, a floating-point number, or a string of characters. This means that a single variable ie. same memory location can be used to store multiple types of data. You can use any built-in or user defined data types inside a union based on your requirement.
The memory occupied by a union will be large enough to hold the largest member of the union. For example, in above example Data type will occupy 20 bytes of memory space because this is the maximum space which can be occupied by character string.
Accessing Union Members
To access any member of a union, we use the member access operator (.). The member access operator is coded as a period between the union variable name and the union member that we wish to access. You would use union keyword to define variables of union type. Following is the example to explain usage of union:
#include <stdio.h>
#include <string.h>

union Data
{
   int i;
   float f;
   char  str[20];
};

int main( )
{
   union Data data;       

   data.i = 10;
   data.f = 220.5;
   strcpy( data.str, "C Programming");

   printf( "data.i : %d\n", data.i);
   printf( "data.f : %f\n", data.f);
   printf( "data.str : %s\n", data.str);

   return 0;
}
When the above code is compiled and executed, it produces the following result:
data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming

Here, we can see that values of i and f members of union got corrupted because final value assigned to the variable has occupied the memory location and this is the reason that the value if str member is getting printed very well. Now let's look into the same example once again where we will use one variable at a time which is the main purpose of having union:

#include <stdio.h>
#include <string.h>

union Data
{
   int i;
   float f;
   char  str[20];
};

int main( )
{
   union Data data;       

   data.i = 10;
   printf( "data.i : %d\n", data.i);
  
   data.f = 220.5;
   printf( "data.f : %f\n", data.f);
  
   strcpy( data.str, "C Programming");
   printf( "data.str : %s\n", data.str);

   return 0;
}

When the above code is compiled and executed, it produces the following result:

data.i : 10
data.f : 220.500000
data.str : C Programming

Here, all the members are getting printed very well because one member is being used at a time.



5.       Typedef
Type definitions make it possible to create your own variable types. The C programming language provides a keyword called typedef, which you can use to give a type a new name. Following is an example to define a term BYTE for one-byte numbers:

typedef unsigned char BYTE;

After this type definitions, the identifier BYTE can be used as an abbreviation for the type unsigned char, for example:.

BYTE  b1, b2;

In the following example we will create a type definition called “intpointer” (a pointer to an integer):

      #include<stdio.h>

      typedef int *int_ptr;

      int main()
      {
            int_ptr myvar;
            return 0;
      }

It is also possible to use type definitions with structures. The name of the type definition of a structure is usually in uppercase letters. Take a look at the example:

      #include<stdio.h>

      typedef struct telephone
      {
            char *name;
            int number;
      }TELEPHONE;

      int main()
      {
            TELEPHONE index;

            index.name = "Jane Doe";
            index.number = 12345;
            printf("Name: %s\n", index.name);
            printf("Telephone number: %d\n", index.number);

            return 0;
      }

Note: The word struct is not needed before TELEPHONE index;



typedef vs #define
The #define is a C-directive which is also used to define the aliases for various data types similar totypedef but with following differences:
  • The typedef is limited to giving symbolic names to types only where as #define can be used to define alias for values as well, like you can define 1 as ONE etc.
  • The typedef interpretation is performed by the compiler where as #define statements are processed by the pre-processor.

Sources:
5. http://www.geeksforgeeks.org/g-fact-53/


      




No comments:

Post a Comment