Friday, 31 May 2013

Null Terminated Strings

The string in C programming language is actually a one-dimensional array of characters which is terminated by a null character '\0'. Thus a null-terminated string contains the characters that comprises of the string followed by a null character. Following are some of the string functions which terminates the output string in a NULL.
  • strcpy- Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
  • strncpy- Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
  • strcat- Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.
  • strcmp- This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.
  • strncmp- This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ, until a terminating null-character is reached, or until num characters match in both strings, whichever happens first.
  • gets- In gets( ) function, the function reads a line from the standard input stream stdin (stdio.h-standard input output header file) and stores it in buffer. The line consists of all characters up to and including the first newline character ('\n'). gets then replaces the newline character with a null character ('\0') before returning the line.
 Rest all string functions terminates the output string at null character or '\0'.

Order of precedence of operators

According to the order of precedence in a logical operator, the first preference between || (Logical OR) and && (Logical AND) is given to logical AND. Below is the list of logical operators according to the preferences given to them in C language:


Floating point representation

Floating point describes the method of representing a real number in a way that it supports a wide range of values in a few significant number so that less amount of memory allocation is used by the computer. The numbers are generally represented in fixed form of significant digits (the mantissa) and is scaled using the exponent and the base is of 2 when the number is binary converted.

significand × baseexponent

152853.5047= 1.528535047 × 10Here if we compare the above generalized equation with the number, we can easily see the significant digits (significand), base (since here the digit is in the form of ten decimal digits of precision so base 10 is used) and exponent.
The location of radix point is indicated by placing explicit characters (dot or comma). If radix point is not specified it is assumed that it would lie at extreme end or at the end of the digit. We need not to store the radix point nor the base in the memory. Storing of significand (with sign) and exponent is only done in memory.




The mantissa is stored using the sign magnitude method where as exponent is stored using excess-N method in the same memory location.




In the above diagram for 32 bit of RAM 30-31 bits (1 bit) is set for the sign bit, 23-30 bits (8 bits) are set for the exponent (in that also 1 bit is assigned to the sign bit of the exponent) ,expressed in excess-127 representation, and 0-22 bits (23 bits) are reserved for the magnitude or fraction or mantissa. Below is an example of a single precision number.




Similar is the case below, for 64 bits of RAM, 1 bit reserved for sign bit, 11 bits for exponent (expressed in excess-1023 format) and rest 52 bits for mantissa.




Over the years, a variety of floating-point representations have been used in computers. However, since the 1990s, the most commonly encountered representation is that defined by the IEEE 754 Floating point Standard.





Thursday, 30 May 2013

Signed Number representation

Signed number can be represented by using four methods:
  1. 1's complement
  2. 2's complement
  3. Sign Method
  • Sign Magnitude Method
  • Sign Extension Method
     4.  Excess-N Method
  • Excess-127 method
  • Excess-1023 method
1.   One's Complement:
It swaps the binary digits from 1 to 0 and vice verse. One's complement ranges from -127 to 127 for a 8 bit byte. It has two representations for signs 00000000 (+0) and 11111111 (-0). Lets look into an example for more elucidation on one's complement:
8 bit One's complement
(43)10 -- (00101011)2 on doing one's complement to the decimal we get (-43)10 -- (11010100)2.
Problems in one's complement is that it takes two zeros ±0 for representing positive and negative values and also due to end carry around condition which is not expected to be in 2's complement.
















2.    Two's Complement:
It also inverts the binary digits i.e. 0 to 1 and vice verse, thereby converting the bits to one's complement's bits but after conversion one is added to the least significant bit (LSB) thereby converting the bits into two's complement's bits. It doesn't have any positive and negative zeros but only one zero.
8 bit Two's Complement
Two's complement ranges from -128 to 127 for a 8 bit byte. This system is the most common method of representing signed integers on computers. It doesn't support addition/subtraction like one's compliment during carry/borrow of the binary number. Lets see  previous example of one's compliment and give a trial by taking two's compliment:
(43)10 -- (00101011)2 on doing one's complement  we get (11010100)2 now adding one to the LSB we get (-43)10 -- (11010101)2 thus getting Two's complement.










3.    Sign Method
3a.   Sign Magnitude Method:
The first bit of a byte is provided to the sign ('+' or '-') known as sign bit. If the bit is set to 0 (zero) its a positive sign and if the it is set to 1 it means negative. The remaining bits in the number indicates the magnitude or mantissa/significand (floating) or absolute value. Hence in a byte 7 bits (except the signs), magnitude can range from 00000000 (0) to 11111111(127). Thus once sign bit is assigned then the range varies from -127 to 127 since zero can be represented into two ways as explained above.
3b.   Sign Extension:
It is an operation of increasing the number of bits of a binary number while preserving the number's sign as well as the number e.g. the number ten is represented in six bits in a binary form (00 1010)2 the sign extend operation increases the word length upto 16 bits and the new representation is like (0000 0000 0000 1010)2 thereby preserving the value as well as its sign too. In case of negative value e.g. -1510 the binary conversion (11 1111 0001)2 using two's complement, and this is sign extended to 16 bits, therefore the new representation is (1111 1111 1111 0001)2. Here one is appended to the MSB on the left tereby keeping the sign as well as the number preserved.

4.    Excess N Method:
Excess N is also called as offset binary or biased representation, uses a pre-specified number N as a biasing value. Here 0 is represented by N and for -N is represented by all zeros. Biased representation are primarily used for the exponent of floating point numbers. The exponent field of a single-precision (32-bit) number as an 8-bit excess-127 field. The double-precision (64-bit) exponent field is an 11-bit excess-1023 field.
8 bit Excess-127

Monday, 27 May 2013

Strings

The way a group of integers can be stored in an integer array, similarly a group of characters can be stored in a character array. These arrays of characters many a times called as Strings. A string constant is a one-dimensional array of characters terminated by a NULL or '\0'. Each character in the array occupies one byte of memory and the last character or the always the terminating character of string in C lang is NULL or '\0'
NOTE: \0 and 0 are not the same as the ASCII value of \0 is 0 and ASCII value of 0 is 48.

Null character can be defined in three types:
  1. '\0'
  2. NULL
  3. #define NULL 0
The terminating null is important, because its only the way that the function, working with string, can know where the string ends. In fact, a string not terminated by a null character is merely a sequence or collection of characters but not a string.

Lets see a program on string.

char str[10]="sat";
printf("%s",str);

Here str[10] is assigned with 10 bytes of memory allocation in which three has been assigned with "sat". Then what happens to rest of the locations? Yet those are wasted but string automatically assign a null character to the end of the characters i.e. after 't' a null character is set in the memory location. I have marked a green colored '%s" in the printf command line. It shows the format of the  printing, and here it is format string so it will print the strings only till the terminating end (NULL).

Suppose you assigned something in a variable str and now you want changes in it how would you do?
It will be like

str[0]='t';    |     *(str+0)='t';
str[1]='a';            *(str+1)='a';
.       |           .
.       |           .
.       |           .
.       |           .
str[n]='B';        |        *(str+n)='B';

So array would cover all the locations of the mentioned string and hence we can probably change the content in the location of the string.














Friday, 24 May 2013

Functions using Pointers

There are various ways to create or call a function using pointers. Here we will discuss few of them. We generally know there are ways of calling a function:
  1. Call by reference, and
  2. Call by value
With the help of the examples I'll let you know what does the above means. First of all let me tell you various ways of creating a new function:

1.   Function without using pointer:
void main ( )
{
        int a=5; 
        int b=6;
        int c;
        c= sum(a,b);
        printf("%d",c);
}
int sum(int a, int b)//Here a and b are dummy variables consisting of the values of a and b from above in different address
{
        return (a+b);
}

In the above code we are seeing a yellow marked command which is called as function calling as it is calling a function 'sum' with parameters 'a' and 'b'. The function 'sum' is defined in a green mark in which we are adding the values of 'a' and 'b' and passing these values in the main() function.
NOTE: The address of variables 'a' and 'b' in the main function is different from the address of the parameters of the 'sum' function. It means both variables are independent of each other.

The value is added in the 'sum' func and returned to main() function, by using return command, in 'c' variable and printing there only. 

2.   Function using Pointers (* and & both):

void main ( )
{
         int a=5,b=6,c;
         c= sum(&a1 , &b1);// here a and b passes the address to the func sum.
         printf("%d",c);
}
int sum(int *a, int *b)//pointers a and b stored with the address of a1 and b1 and pointing towards their value
{
         return (*a+*b);
}

Here we are using pointers in the parameters of the function because pointers points towards the value stored in the address which is stored in the pointer variable. The operation is similar to that of the above but the thing is way of representing it.

3.   Function using Pointers (& only):

void main ( )
{
         int a=5,b=6,c;
         c= sum(&a1 , &b1);
         printf("%d",c);
}
int sum (int &a1 , int &b1) //a1 and b1 points to the address of a and b in main func
{
         return (a1+b1);
}

4.   Function using Pointers (& once):

Call by Reference:

void main ( )
{
         int a=5,b=6,c;
         sum(a , b, c);
         printf("%d",c);
}
int sum(int a, int b, int &c)
{
         c= a+b;
}

Here &c refers c from main( ) function and stores the value in the same address without creating a new allocation for the value. This is called call by reference.

5.   Function using Pointer:

void main ( )
{
         int a=5,b=6,c;
         sum(a , b, &c);
         printf("%d",c);
}
int sum(int a, int b, int *c)
{
         *c= a+b;
}

Here int *c, parameter of sum func, is a pointer and it points towards the address of the c variable defined in the main.










Tuesday, 21 May 2013

Arrays and Pointers

Before starting with Arrays and Pointers lets have a look on basics of operating systems (OS), their types and their use in the programming language. An operating system (OS) is a collection of software that manages computer hardware resources and provides common services for computer programs. Types of OS are DOS, UNIX (LINUX, CentOS, AIX (IBM), Red Hat, Ubuntu, etc), Windows (95, 98, 2K, Me, XP, Vista, 7, 8, etc), SUN, Mac, etc. People generally use windows as a operating system, since it is user friendly and computation is done easily in it, so here we'll be talking about windows OS only. Windows uses visual studio as an integrated development environment (IDE) built by microsoft. Visual studio is used, as we can make changes in applications within the operating system. This OS comes under 32-bits and 64 bits earlier 16-bit was used but its now not used in a programming language. All OS has a microprocessor (µp) and they also comes in 32 and 64 bits. The windows OS of either 32 bits or of 64 bits can work in 64 bits of the µp. The use of OS is to operate applications and they too come in 32 and 64 bits. An application with 32 bit can be operated in 32 bits or 64 bits of the OS but an application of 64 bits cannot be operated in 32 bits OS rather it is operated in 64 bit OS.
Visual studio can create an app of either 32-bits, 64-bits, Itanium Architecture (produced by intel) and any (can be 32 bits, 64-bits or IA). In my earlier blog of datatypes, I talked about the sizes of datatypes, it varies across the OS.

Below is a table of data models:



ARRAYS:

RAM is a 1-dimensional sequence of locations. Each location has its own address and size. In a programming language when we define a variable, automatically RAM provides the space to the variable.
Lets see with an example:

int a;

Since we know "int" datatype is of 4 bytes so here it requests RAM to allocate 4 bytes in the memory. The location is provided with a name "a" (termed as variable) and then the compiler stores the integer into that memory location.
In case of arrays the memory occupied depends on the number of elements given by the user.

int a[10];

Here the number of elements selected is 10 and since the the datatype is of 4 bytes so here it requests RAM to provide 4*10 bytes i.e. 40 bytes of allocation in the memory. The array named "a" has 10 elements in it and each element is of 4 bytes so the memory used by the RAM is 40 bytes.
NOTE: Name of the array decays into address of the 1st element of the array.

int a;
printf("%d",a)

In the above code, the printf command will print the address of the variable, as the value is not assigned to the variable so by default it will show the address.
In 2-D array the memory allocation is dependent upon the n by m matrix:

int a[n][m];

Here n*m*4 bytes of memory is allocated in the RAM.
For calculation of 1-D array in a memory can be represented as following:

a[0]--> a + 0* sizeof (a)
a[5]--> a + 5* sizeof (a)

Here '[ ]' (square brackets) are called as indexing operators.
For calculation of 2-D array there are two orders:
  1. Row major order
  2. Column major order
for row major order the memory calculation is done as follows:

a[i][j]--> a + (i * m + j)* sizeof (a)

where a= base address
i, j= index values
m= total number of columns

for column major order the memory calculation is done as follows:

a[i][j]--> a + (i + j * n)* sizeof (a)


where a= base address
i, j= index values
n= total number of rows

But here the question arises that these operations can not be done simultaneously, then what does C/C++ programming will support from the above? So the answer is C/C++ lang supports row major order where as column major order is supported by matlab.

Now if we assign a value to a variable its stored in 4 bytes (32-bits) of memory allocated by RAM in a binary form. Here's an example for understanding it more simpler form:

int a=5;

Here two things pops out LSB and MSB. MSB is the most significant bit and LSB is the least significant bit. And the allocation of the memory starts from LSB to MSB. In our case LSB is 101 and rest are 0 and is represented as:


0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  1
MSB                                                                                                            LSB


POINTERS:

Pointers are those which stores the address. Consider the declaration,

int a=5;
int *ptr;
ptr= &a;

Here variable "a" is assigned a value at some address let it be 100. '*' (Asterisk) is a pointer operator and is called "value at address" operator. It returns the value stored at a particular address. It is also called as 'dereferencing' operator. The other pointer operator is '&' (Ampersand), called 'address of' operator. The expression &a returns the address of the variable a, which in this case happens to be 100.

Uses of the '*' operator:
  • Multiplication
  • create/declare a pointer
  • dereference a pointer

Uses of the '&' operator:
  • Logical AND (&&)
  • Bitwise AND (&)
  • referencing a pointer
NOTE: Size of all pointers is 32-bits on a 32-bit OS and size of all pointers is 64 bits on a 64 bit OS.

Lets see some more commands on pointers which will let you know more about the pointers:

int a=5;              100[   5   ]a
int *ptr= &a;           1000[   100   ]ptr
int **aptr= &ptr;        10000[   1000   ]aptr
int ***aaptr= &aptr;      20000[   10000   ]aaptr

*ptr means the value stored at the address contained in ptr or ptr is a pointer to integer a.
**aptr means aptr is a pointer to a pointer to integer a.
***aaptr means aaptr is a pointer to a pointer to a pointer to integer a.


int size[10];\\valid operation
int a[size];\\invalid operation

In the above program the first command given is valid because here we directly assigning a constant value 10 in the indexing operator. But in the second case since size is not a constant variable or a value so it is not a valid operation. It can be done in the following manner:

const int size[10];
int a[size];

Now here we have a constant variable size with 10 elements in it, so the next command is valid now as size is a constant integer. The program further can also be coded as:

#define size 10
int a[size];


Here #define defines the global constant of value of size to be 10 throughout the program. So the next line of the code is also valid for execution.