Saturday, November 14, 2015

Array, Multidimensional array

Array

Collection of similar type of data type called array. When we declare an integer or character variables, it requires memory space according to their data types. If program needs multiple variable to store value or to be used in later part of program, it is not good practice to declare similar data type variables again and again. Hence, To overcome this multiple declaration of variables, array is used. In array we can represent group of similar data by a single group name called array name and each item in an array called item or component of the array.


 storage-class data-type array-name[expression]; 

storage-class : type of storage class use(external,static, auto, register).
data-type : indicates types of array integer, character, float or structure type.
array-name : can be any name used to represent the array.
expression : this is the size of array, represents the number of elements in array and can be any positive integer value ranged allowed in programming.

Size of an array is multiplication of index and its size of data type.

Array stores each element sequentially in a fixed location, For example fist element of array stored in first reserved location, second on second reserved location, and so on until the last element stored in the last reserved location of array.

To access individual elements in an array requires some unique means of identifying each element. Since elements in the array are stored sequentially, any individual element can be accessed by giving the name of the array and the element's position. This position is called the element's subscript or index value. Better can be understood with examples given below.

ex:
int arr[10];   
 or  
 char str[100];  
 or  
 float[10];  

array "arr" is an integer array of size 10, but actual size in terms of memory be the 10*sizeof(int).

array indexing starts with zero so fist element of array is

arr[0] ,
2nd element arr[1],
.....
arr[expression-1] is last element of any array.




One Dimensional Array 
  Above arrays are example of One Dimensional array, also known as single-dimension array or a list. This is simplest form of array.

Modification of any element in single dimestion array usually done by directly accessing the element by its index value

Suppose if we want to access 4th element of bwlo array
int arr[8] = {3,5,8,1,7,2,9,4};  

Then,
 int value = arr[3]; //Directly accessing 4th index from 0 
 printf("Value = %d\n",value);  

Output

Value = 1  


Multidimensional Array

Array can be of any dimension, depends on what to implement. A better way to represent all dimension  in single example
 storage-class data-type array-name [expression 1] [expression 2] [expression 3]......[expression n];  

2x2,3x3 or nxn matrix is example of two dimensional array.



Array representation of 3x3 Matrix

int arr[row][column] = { {row0,col0},{row0,col1},{row0,col2},{row1,col0},{row1,col1},{row1,col2}, {row2,col0},{row2,col1},{row2,col2} };


Ex-



#include <stdio.h>  
 #define ROW 3  
 #define COL 3  
 main()  
 {  
     int matrix[ROW][COL] = { {2,6,8},{9,1,4},{7,8,3}};  
     int i,j;  
     printf("Matrix\n");  
     for(i=0; i < ROW; i++)  
     {  
         for(j=0; j < COL; j++)  
         {  
             printf("%d\t",matrix[i][j]);  
         }  
         printf("\n");  
     }  
 }  

Output
 $ gcc matrix.c   
 $ ./a.out   
 Matrix  
 2    6    8      
 9    1    4      
 7    8    3     

Three Dimensional Array 
Adding one more expression to array,

storage-class data-type array-name [expression 1] [expression 2] [expression 3];

If characters in a lines of a page can represent one dimensional array then a page filled with multiple line can represent two dimensional array and number of pages in a book can be a three dimensional array.

#define PAGES 30  //Number of pages in book
#define LINES 15  // Number of lines in one page
#define CHARACTERS 40   //Number of characters in one line
   
int book[PAGES][LINES][CHARACTERS];  


Reference :
Programming with C by Byron Gottfried.


Tuesday, November 10, 2015

Ellipses Operator (. . .)

This operator is used to represent various number of parameters involve. This is mainly used in function arguments , when the number of arguments is not known.

Ex -
int foo(int i, int j, . . .);

But we can use ellipses operator in other part of coding also.

In switch case

 main()  
 {  
     --------  
     --------  
     switch(3)  
     {  
         case 1 ... 4:  
           printf("Option is between 1 to 4);  
           break;  
         case 5 ... 9:  
           printf("Option is between 5 to 9);  
           break;  
     }  
 }  

In array

Ellipses operator used in array initialization also. Using this operator we can partially initialize our arrays.

Ex - 

 main()  
 {  
      int arr[] = { [0 ... 4] 4, [5 ... 9] 5};  
      printf("arr[0] %d\n", arr[0]);  
      printf("arr[6] %d\n", arr[6]);  
 }  
 o/p -   
 arr[0] 4  
 arr[6] 5  
 Partially initialize the array   
 main()  
 {  
     int arr[10] = { [3]5, [1] = 4, [4] 3, [0] = 0 };  
      printf("arr[0] %d\n", arr[0]);  
      printf("arr[3] %d\n", arr[3]);  
      printf("arr[4] %d\n", arr[4]);  
 }  
 o/p -   
 arr[0] 0  
 arr[3] 5  
 arr[4] 3  

Storage classes in C

Storage class defines the memory region that program variables an function going to use. Storage class also defines the scope of variables and function, how far and how long they can be used in program. They are mainly of four types
1. Auto or Local
2. Static
3. External
4. register

Automatic or Local 

local variables have very limited scope in program, its life time is only limited to function scope. as long as function in execution state variables retain their value and cleared as soon as it function comes out form execution. So it is very simple all variable declared inside function body is called local variable and their scope is within the function body, we can not access their value out side from the function. All local variables are stored in Stack.

Why auto or local variables can't retain their values because, stacks gets cleared after every execution and new set of function and variables will be loaded. So memory address given for a variable no longer available and no value is stored.

'auto' keyword used to define local variables, but it is optional.

Prototype
auto data-type variable-name  

Static

Statically defined variable and function has file scope. File scope means they can accessible within the file, out side of file it wont retain their values. It retains their value(last modified value) within the file.
Even is declared within function body, it retain its last modified value but its scope is limited to the function body itself.

But if it is declared globally it will be accessible by all the function used in that file.

As i mentioned in above statement Static is limited to file only so same variable name can be used in the other files also. but it will created confusion for programmer. so try to avoid.

Yes but if it is used with function then it will become very easy for programmer to use same function name but different bodies in different files.

statically defined variables are stored in BSS segment , if uninitialized and data segment, if initialized.

'static' keyword is used to define static storage class.

Prototype

static data-type variable-name  
or
static return-data-type function-name (arg1, arg2, ...);  

External 

External variables have global scope. they can be accessible my anywhere from the code or file it it is exported into that files. They can retain their values al long as program is running. External variables  are stored in BSS segment , if uninitialized and data segment, if initialized.

Functions used without storage class is External by default. To make function static  or local we have to use static or auto keyword explicitly.

 extern data-type variable-name  

Register 

Resister is equivalent to auto except that register variables are stored in register not in physical memory(RAM) and it is way out faster then auto. But size of registers are very small, depends on the system architecture. Whenever size of register gets full it will automatically store next variables to
stack without giving any prior notice.

'register' keyword is used to declare register variables.

register data-type variable-name  

Memory layout of C Program




Above diagram gives an over view of how memory is organized for C program. where all variable(global and local), functions and dynamic memory get stored. 

Why this layout is needed ?

Actually memory layout is just a representation of memory region for different kinds of symbol used in C program. It is needed because variable and kind of memory allocation (static, dynamic)we use in C can not be stored in same place. Based on modifier used for variables compiler decides the memory reason. some of the memory allocate dynamically(on run time), They have separate memory region for allocation.

Detail explanation of each segment ...

Stack 

This is the upper segment of memory layout and this region is used to store all local variables, function calling. This gets cleared once use of that function or local variable is over. So it does not hold value of any its variable for long time. life time of value stored in this region is as long as the function in execution state. All memory and its value automatically gets freed as the function comes out form execution.

Working of stack is last in first out(LIFO). Filling stack depends from machine to machine, in x86 system stack starts growing towards address 0, from top to bottom for above given diagram. 

Heap

Heap is the segment where all dynamic allocation of memory takes place. dynamic allocation of memory is nothing but memory allocation at run time using malloc(), calloc() and realloc(). Heap starts growing from bottom to top, in above figure from BSS to Free space. Filling of heap purely depends on the function we are using for memory allocation melloc(), calloc() or realloc() and it can be freed by using free() function. 

Heap memory segment is very sensitive memory reason any kind of memory corruption can lead to a catastrophe. Programmer should allocate memory as exactly as required and free them as soon as utility is over. Because program does not free the memory automatically like Stack memory region.

BSS(Block Started by Symbol) also called Uninitialized data segment 

This is also called uninitialized memory segment where all global and static uninitialized variable gets saved. In this region all variables get automatically initialized with Zero, if it is not explicitly initialized. 

Data segment or initialized data segment 

Data segment is the region where all the initialized global and static variables get stored. This segment is further divided into two segment 1) Read only initialized segment 2) read-Write initialized segment. 

 In read-only initialized  segment all pointer initialized with string, gets stored in this region, programmer can not change the value at any index. If const key word is used for any variable, that also go to read-only initialized segment only. whereas any global character array initialized with any string, then string values can be changed at any point of time by programmer.

Both can be illustrated by following examples.
 #include <stdio.h>  
 char *temp = "hello";  
 char temp1[] = "yahoo";  
 main()  
 {  
     char *str = "world";  
     temp1[2] = 'd'; // Correct  
     *(temp+2) = 'g'; // Not possible  
     *(str + 2) = 'k'; // Not possible  
     printf("temp = %s\t str = %s \t temp1 = %s\n",temp,str,temp1);  
 }  

In above example three type of initialized taken into consideration. If we complie the code and try to do run it. it will give Segmentation fault . why because  we are trying to change some Constant type of parameters. 

char *temp = "hello" this will be stored in read-only initialized segment(constant segment) . temp1 is simple character array so this will go to read-write initialized data segment.



Text Segment or code segment 

All code syntax and instructions of program is stored in Text segment only. This region is read only, to prevent any over writing by any other overflowed region. 

To check sized used for bss and text we have one command called 'size'.

 $ size a.out   
   text      data      bss      dec      hex    filename  
   1290      574       2      1866      74a    a.out  

References 

https://en.wikipedia.org/wiki/.bss

Monday, November 9, 2015

Compilation steps in C

Before generating any executable file, program has to travel many stages of compilation. each stage of compilation has its own significance. If it fails at any step it may not lead to further. So it is programmer responsibility to make compiler happy.

Stages are -

1) Pre-processing
2) Compilation
3) Assembler
4) Linker

Pre-processing

This is the very first stage of compilation. at this all stage all includes files, macro defines get expended and if any issue with include file it will display here itself. it is better illustrated with following example hello.c

 #include <stdio.h>  
 #define MAX 100  
 int main()  
 {  
      printf("MAX : %d\n",MAX); return 0;  
 }  

Now compile the above code, to see just Pre-processing stage, compile with following options
$ gcc -E Hello_world.c  

-E options expand all macros, but it will display all expansion on terminal itself. A better way to keep all into a single file is redirect to a file with extension .i.
$ gcc -E Hello_world.c > hello.i   
$ ls  
 hello.c hello.i

or
 $ gcc -save-temps hello.c   
 $ ls  
 a.out hello.c hello.i hello.o hello.s  
 
If -save-temps option is used in compilation, then all stage file generate in one shot. that we dont want now..

Compilation

 All code here after will convert into machine language(low level language) hello.s. To illustrate this -S option can be used which produce hello.s file
 $ gcc -S hello.i   
 $ ls  
 hello.c hello.s  

And hello.s file will look like

$ cat hello.s  
     .file    "hello.c"  
     .section    .rodata  
 .LC0:  
     .string    "MAX : %d\n"  
     .text  
     .globl    main  
     .type    main, @function  
 main:  
 .LFB0:  
     .cfi_startproc  
     pushq    %rbp  
     .cfi_def_cfa_offset 16  
     .cfi_offset 6, -16  
     movq    %rsp, %rbp  
     .cfi_def_cfa_register 6  
     movl    $100, %esi  
     movl    $.LC0, %edi  
     movl    $0, %eax  
     call    printf  
     movl    $0, %eax  
     popq    %rbp  
     .cfi_def_cfa 7, 8  
     ret  
     .cfi_endproc  
 .LFE0:  
     .size    main, .-main  
     .ident    "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"  
     .section    .note.GNU-stack,"",@progbits  

Assembler 

Here is the stage where all syntax used in c program is checked. If any syntax error or function prototype mismatch or unused variable, undefined variable, redefine variables preset in the code, will be thrown as error or warning by the compiler .In this stage all code converts from machine code to object code and one object file is generated with extension of hello.o. That can be seen separately by using following command.
 $ gcc -Wall -c hello.s  
 $ ls  
 hello.c hello.o hello.s  

-Wall gcc option will throw all kind of warning that was found during compilation. If everything goes smooth the an object file will be generated which is nothing but complied file only that contains all symbols (all global variables, functions etc.. ) used in code.

Linker

This is last and final stage of compilation where all the linker combine all symbol objects together and form an executable file. if any Static library used in code that also linked at this stage only by using -l<lib name> option.
 $ gcc -o run hello.s  
 or  
 $ gcc -o run hello.c  
 or  
 $ gcc -o run hello.o  
 or  
 $ gcc -o run hello.i  
 $ ls  
 hello.c hello.i hello.o hello.s run  

an executable file 'run' is generated.  Now run the 'run'.
 $ ./run   
 MAX : 100  

Note. you can notice that #define MAX 100 replace second argument of printf(), but not in first one because first argument is treated as control string or like string. that is why out put looks like
MAX : 100