ASIC Verification: February 2008

Friday, February 29, 2008

C Basics

What are constant and Variables in C?

A constant is an entity that doesn’t change whereas a variable is an entity that may vary during program execution. The results of any calculations are stored in computers memory. To make the retrieval and usage of these results easy, these memory locations are given names. Since the value stored in each location may change, the names given to these locations are called variable names. These locations can contain integer, real or character constants.

What are the types of constants used in C?

Integer constants - Maximum allowable range is b/w -32768 and 32767.
Ex: 426, +782, -8000, -7605

Real constants expressed in Fractional form - It must have a decimal point.
Ex: +325.34, 426.0, -32.76, -48.5792

Real constants expressed in Exponential form - Used, if the constant value is too small or too high. Range of these constants is -3.4e38 to 3.4e38.
Ex: +3.2e-5, 4.1e8, -0.2e+3, -3.2e-5

Character constants - A character constant is a single alphabet, a single digit or a single special symbol enclosed within single inverted commas. Both the inverted commas should point to the left.

What are the C keywords?

Keywords are the words whose meaning has already been explained to the C compiler. The keywords cannot be used as variable names because if we do so, we are trying to assign a new meaning to the keyword, which is not allowed by the computer.

What is the meaning of ampersand (&) operator?

The ampersand (&) before the variables in the scanf( ) function is a must. & is an ‘Address of’ operator. It gives the location number used by the variable in memory. When we say &a, we are telling scanf( ), at which memory location should it store the value supplied by the user from the keyboard.

What are the types of instructions in C?

  • Type Declaration Instruction - To declare the type of variable used in C
  • Arithmetic Instruction - To perform an arithmetic operations
  • Control Instruction - To control the sequence of execution
What are the rules used for converting integer and float values?
  1. An arithmetic operation between an integer and integer always yields an integer result.
  2. An operation between a real and real always yields a real result.
  3. An operation between an integer and real always yields a real result. In this operation the integer is first promoted to a real and then the operation is performed. Hence the result is real.
How a decision control instruction is implemented in C?
  1. The if statement
  2. The if-else statement
  3. The conditional operators
Hierarchy of operators

! - Logical NOT
* / % - Arithmetic and modulus
+ - - Arithmetic
< > <= >= - Relational
== != - Relational
&& - Logical AND
|| - Logical OR
= - Assignment

What is the conditional operators in C?

The conditional operators ? and : are sometimes called ternary operators, since they take three arguments. Their general form is,

expression 1 ? expression 2 : expression 3;

“if expression 1 is true (that is, if its value is non-zero), then the value returned will be expression 2, otherwise the value returned will be expression 3”.

What are the compound assignment operator?

Consider the following program:

main()
{
int i=1;
while (i<5)
{
printf("%d", i);
i+=1;
} // End of while loop
} // End of main()

Here += is an compound assignment operator. It increments the value of i by 1. Other compound operators are -=, *=, /+, %=.

Tell me about the break statement

We often come across situations where we want to jump out of a loop instantly, without waiting to get back to the conditional test. The keyword "break" allows us to do this. When break is encountered inside any loop, control automatically passes to the first statement after the loop. A break is usually associated with an if statement.

Tell me about the continue statement

In some programming situations we want to take the control to the beginning of the loop, bypassing the statements inside the loop, which have not yet been executed. The keyword continue allows us to do this. When continue is encountered inside any loop, control automatically passes to the beginning of the loop.

What is the difference b/w while and do-while loop?

This difference is the place where the condition is tested. The while tests the condition before executing any of the statements within the while loop. As against this, the do-while tests the condition after having executed the statements within the loop.

Tell me about the switch control statement

The control statement that allows us to make a decision from the number of choices is called a switch-case-default, since these three keywords go together to make up the control statement. They most often appear as follows:

switch ( integer expression )
{
case constant 1 : do this ;
case constant 2 : do this ;
case constant 3 : do this ;
default : do this ;
}

The integer expression following the keyword switch is any C expression that will yield an integer value. It could be an integer constant like 1, 2 or 3, or an expression that evaluates to an integer.

Is switch a replacement for if?

Yes and no. Yes, because it offers a better way of writing programs as compared to if, and no because in certain situations we are left with no choice but to use if. The disadvantage of switch is that one cannot have a case in a switch which looks like:

case i <= 20 :

All that we can have after the case is an int constant or a char constant or an expression that evaluates to one of these constants. Even a float is not allowed.

What is the advantage of switch over if?

Switch leads to a more structured program and the level of indentation is manageable, more so if there are multiple statements within each case of a switch.

What are the things that you can't do with switch?
  1. A float expression cannot be tested using a switch
  2. Cases can never have variable expressions (for example it is wrong to say case a +3 : )
  3. Multiple cases cannot use same expression. Thus the following switch is illegal:
switch ( a )
{
case 3 :
...
case 1 + 2 : // Illegal
...
}

(a), (b) and (c) above may lead you to believe that these are obvious disadvantages with a switch, especially since there weren’t any such limitations with if-else.


Thursday, February 28, 2008

C File Handling

C communicates with files using a new data type called a "file pointer". This type is defined within the library stdio.h, and written as FILE *. A file pointer called output_file is declared in a statement like

FILE *fp;

Your program must open a file before it can access it. This is done using the "fopen()" function, which returns the required file pointer. If the file cannot be opened for any reason then the value NULL will be returned. You will usually use "fopen" as follows

if ((fp = fopen("name of the file to open", "w")) == NULL)
fprintf(stderr, "Can't open %s\n", "fp");

fopen takes two arguments, both are strings, the first is the name of the file to be opened, the second is an access character, which is usually one of:

"r" or "w" or "a" or "r+" or "w+" or "a+". we will discuss these modes in detail in a later section.

Now let us take a simple program that will read a file and count how many characters, spaces, tabs and newlines are present in that file.
====================================================================================
main()
{
FILE *fp; /* file pointer fp*/
char ch;
int number_of_lines=0, number_of_tabs=0,
number_of_blanks=0, number_of_char=0;

fp=fopen("ex.c", "r");

while(1)
{
ch = fgetc(fp);
if(ch == EOF) break;
number_of_char++;

if(ch == ' ') number_of_blanks++;
if(ch == '\n') number_of_lines++;
if(ch == '\t') number_of_tabs++;
}
fclose(fp);
printf("Number of characters in the file = %d\n", number_of_char);
}
====================================================================================

Opening a file establishes a link b/w a program and OS about which file we are going to open and how. We provide the OS the name of the file and whether we plan to read or write to it. The link b/w our program and OS is a structure called FILE which has been defined in the header file called stdio.h. When we request the OS to open a file, what we get back is a pointer to the structure FILE. Thats why we make the following declaration before opening the file,

FILE *fp;

The FILE structure contains information about the file being used, such as its current size, its location in memory and a character pointer which points to the character that is about to get read. Now lets understand the following statements:

FILE *fp;
/* fp is a file pointer which contains address of the structure FILE*/
fp=fopen("ex.c", "r");

fopen() performs 3 tasks:

  • It searches on the disk the file to be opened.
  • If the file is presents, it loads the file from the disk into memory.
  • It sets up a character pointer which points to the first character of the chunk of the memory where the file is loaded.
Reading from a file

To read the file contents in the memory, there exists a function called fgetc().

ch = fgetc(fp);

fgetc() reads the character from the current file pointer position, advances the pointer position so that it now points to the next character, and returns the character it read, which we collected in the variable ch. While reading from the file, when fgetc() encounters the special character whose ASCII value is 26, it returns the macro EOF. The EOF macro has been defined in stdio.h.

Closing the file

When we have finished reading from the file, we need to close it. This is done using the function fclose() through the statement,

flose(fp);

File opening modes

Following is a list of all possible modes in which a file can be opened.

"r" - Reading from the file.

"w" - Writing into the file.

"a" - Appending new contents at the end of the file.

"r+" - Reading existing contents, Writing new contents, modifying existing contents.

"w+" - Writing new contents, Reading them back and modifying the existing contents.

"a+" - Reading existing contents, appending the new contents. Can't modify the existing contents.

Standard DOS devices

To perform reading or writing operations on a file, we need to use the function fopen(), which sets up a file pointer to refer to this file. MS-DOS also predefines file pointers for standard files.

stdin - Standard input device (Keyboard);

stdout - Standard output device (VDU);

stderr - Standard error device;

stdaux - Standard auxiliary device;

stdprn - Standard printing device;

Thus the statement ch = fgetc(stdin) would read a character from the keyboard rather than from a file.

fputc(ch, stdprn) writes a character read from the file to the printer.

Text mode versus Binary mode

There are 3 main areas where text and binary mode files are different. These are:

  1. Handling of new lines
  2. Representation of end of file
  3. Storage numbers

I am not going into detail about these things.

Record I/O in files

So far we have seen programs which write characters, strings or numbers to a file. If we desire to write a combination of dissimilar data types, what should we do? We all know, use structures. Following program illustrates the use of structures for writing records of employees.

====================================================================================

/*Writing records to a file using structures*/

#include "stdio.h"
main()
{
FILE *fp;
char another ='Y';
struct emp
{
int age;
char name[25];
float basic_sal;
} e;
fp = fopen("Employees_details.txt", "w");

if(fp == NULL)
{
printf("Can't open the write file\n");
exit();
}

while(another == 'Y')
{
printf("Enter the name of the employee, age and his bs\n");
scanf("%s%d%f", &e.name , &e.age , &e.basic_sal);

fprintf(fp, "%s %d %f\n", e.name , e.age , e.basic_sal);
printf("Add another record(Y/N)\n");
fflush(stdin);
another = getchar();
}
fclose(fp);
}

====================================================================================

The above program has two disadvantages:

Guess....???

  • The numbers would occupy more number of bytes, since the file has been in text mode. This is because when the file is opened in text mode, each number is stored as a character string.
  • If the number of fields in the structure increase, writing structures using fprintf(), or reading them using fscanf(), becomes quite clumsy.
Let us now see more efficient way of reading/writing structures. This makes use of two functions fread() and fwrite().

====================================================================================

main()
{
FILE *fp;
char another ='Y';

struct emp
{
int age;
char name[ 25];
float basic_sal;
} e;

fp = fopen("Employees_details.txt", "w");

if(fp == NULL)
{
printf("Can't open the write file\n");
exit();
}

while(another == 'Y')
{
printf("Enter the name of the employee, age and his bs\n");
scanf("%s%d%f", &e.name, &e.age, &e.basic_sal);
fwrite(&e, sizeof(e), 1,fp);
printf("Add another record(Y/N)");
fflush(stdin);
another = getchar();
}
fclose(fp);
} // End of main()

====================================================================================

Consider the statement:

fwrite (&e, sizeof (e), 1, fp);

Here, first argument is the address of the structure to be written to the disk. The second argument is the size of the structure in bytes. Instead of counting the bytes ourselves, we let the program do it for us by using the sizeof() operator. The third argument is the number of structures that we want to write at one time. In this case, we want to write only one structure at a time. The last argument is the pointer to the file we want to write to.

Reference

"Let us C" by Yashavant Kanethkar.


Tuesday, February 26, 2008

C Strings

You must become familiar with the pointer concepts to use C strings effectively. Once you get used to them, you can often perform string manipulations more efficiently.

A string in C is simply an array of characters. The following line declares an array that can hold a string of up to 99 characters.

char str[100];

str[0] is the first character of the string, str[1] is the second character, and so on. But why is a 100-element array unable to hold up to 100 characters? Because C uses null-terminated strings, which means that the end of any string is marked by the ASCII value 0 (the null character), which is also represented in C as '\0'.

The following is a representation of what would be in RAM, if the string "Hello, world!" is stored in this array.

characters : H e l l o , w o r l d !
Hex values : 48 65 6C 6c 6F 2C 20 77 6F 71 6C 64 21 00
Subscripts : 0 1 2 3 4 5 6 7 8 9 10 11 12 13

The name of the array is treated as a pointer to the array. The subscript serves as the offset into the array, i.e., the number of bytes from the starting memory location of the array. Thus, both of the following will save the address of the 0th character in the pointer variable ptr.

ptr = str;
ptr = &str[0];


In what way are character arrays different than numeric arrays?
Can elements in a character array be accessed in the same way as the elements of a numeric array?
Do I need to take any special care of '\0'?
Why numeric arrays don't end with a '0'?
===================================================================
/*program to demonstrate printing of a string*/
main()
{
char name[ ] = "Suresh"; /*initialized a character array*/
int i=0;
while(i<=5)
{
printf("%c", name[i]);
i++;
} // End of while
} // End of main()
===================================================================
can we write the while loop without using the final 5? We can. Because each character array always
ends with a '\0'.
===================================================================
main()
{
char name[ ] = "Suresh"; /*initialized a character array*/
int i=0;
while(name[i] != '\0')
{
printf("%c", name[i]);
i++;
} // End of loop
} // End of main()

===================================================================
Accessing array elements using the Pointers:
===================================================================
main() {
char name[ ] = "Suresh"; /*initialized a character array*/
char *ptr;
ptr = name;
/* store base address*/
while(*ptr != '\0')
{
printf("%c", *ptr);
ptr++;

}
// End of loop
} // End of main()
===================================================================
In fact, the character array elements are accessed in the same way as the elements of an integer array.

More on Strings

The length of the string should not exceed the dimension of the character array. This is because C compiler doesn't perform bound checking.

scanf() is not capable of receiving multi-word strings. Therefore, names such as Suresh Chellappa would be unacceptable. The way to get around the problem is by using the function gets().
===================================================================
main()
{
char name[25];
printf("Enter your full name\n");
gets(name);
puts("Hello");
puts(name);

}

====================================================================================
Two dimensional array of characters

Now let us look at an example for 2-D array of characters:
====================================================================================
#define FOUND 1
#define NOTFOUND 0
main()
{
char master_list[5][10] =
{ "ASIC", "FPGA", "DFT", "STA","PANDR"};

int i, flag, a;
char yourfield[10];
printf("Enter your Field\n");
scanf("%s", &yourfield);
flag = NOTFOUND;
for(i=0; i<= 4; i++)
{
a = strcmp(&master_list[i][0], yourfield);
if (a==0)
{
printf("Your filed is related to ASIC\n");
flag = FOUND;
break;
} // End of if condition
} // End of for loop
if(flag == NOTFOUND)
printf("Sorry man\n");
}

====================================================================================
strlen()

Syntax: len = strlen(ptr); where len is an integer and ptr is a pointer to char.

strlen() returns the length of a string, excluding the null. The following code will result in len having the value 13.

int len;
char str[15];
strcpy(str, "Hello, world!");
len = strlen(str);

strcpy()

Syntax: strcpy(ptr1, ptr2); where ptr1 and ptr2 are pointers to char.

strcpy() is used to copy a null-terminated string into a variable. Given the following declarations, several things are possible.

char S[25];
char D[25];
  • Putting text into a string:
    strcpy(S, "This is String 1.");
  • Copying a whole string from S to D:
    strcpy(D, S); 
strcat()

Syntax: strcat(ptr1, ptr2); where ptr1 and ptr2 are pointers to char.

strcat() is used to concatenate a null-terminated string to end of another string variable. This is equivalent to pasting one string onto the end of another, overwriting the null terminator. There is only one common use for strcat().

char S[25] = "world!";
char D[25] = "Hello, ";
  • Concatenating the whole string S onto D:
    strcat(D, S);
strcmp()

Syntax: diff = strcmp(ptr1, ptr2); where diff is an integer and ptr1 and ptr2 are pointers to char.

strcmp() is used to compare two strings. The strings are compared character by character starting at the characters pointed at by the two pointers. If the strings are identical, the integer value zero (0) is returned. As soon as a difference is found, the comparison is halted and if the ASCII value at the point of difference in the first string is less than that in the second (e.g. 'a' 0x61 vs. 'e' 0x65) a negative value is returned; otherwise, a positive value is returned. Examine the following examples.

char s1[25] = "pat";
char s2[25] = "pet";

diff will have a negative value after the following statement is executed.

diff = strcmp(s1, s2);

diff will have a positive value after the following statement is executed.

diff = strcmp(s2, s1);

diff will have a value of zero (0) after the execution of the following statement, which compares s1 with itself.

diff = strcmp(s1, s1);

Questions

What is the difference b/w strcpy and memcpy? When should each be used?
How can I convert a string into number?
How can I convert a number into string?
How do you print only the part of the string?
How do I know, how many elements an array can hold?

Monday, February 25, 2008

C Structures

We already know that arrays are many variables of the same type grouped together under the same name. Structures are like arrays except that they allow many variables of different types grouped together under the same name. For example you can create a structure called book which is made up of a string for the name, float for the prize and an integer for pages. Here is how you would create that book structure in C:


===========================================================================
main()
{
char name[2];
float price[2];
int i,pages[2];

printf("Enter the name, price and pages of 2 books\n");

for(i=0; i<=1; i++)
scanf("%s%f%d", &name[i], &price[i], &pages[i]);
printf("U have entered\n");
for(i=0; i<=1; i++)
printf("%c %f %d\n", name[i], price[i], pages[i]);

}
===========================================================================

and here is the sample run:

Enter the names, prizes and pages of 2 books
A 100.0 320
B 210.25 452

U have entered
A 100.0 320
B 210.25 452

This approach allows you to store name, prize and pages of a book. But the program becomes more difficult to handle as the number of items relating to the book go on increasing. A structure contains a number of data types grouped together, these data types may be or may not be of the same type. The following example illustrates this data type:
===========================================================================
main()
{
struct book
{
char name;
float price;
int pages;
}b1, b2;

printf ("Enter name, price and pages of 2 books\n");
scanf("%s%f%d", &b1.name, &b1.price, &b1.pages);
scanf("%s%f%d", &b2.name, &b2.price, &b2.pages);

printf ("And this is what u entered\n");
printf("%c %f %d\n", b1.name, b1.price, b1.pages);
printf("%c %f %d\n", b2.name, b2.price, b2.pages);
}
===========================================================================
and here is the output;
Enter name, price and pages of 2 books
A 100.0 320
B 210.25 452

And this is what u entered
A 100.0 320
B 210.25 452

The program demonstrates two fundamentals aspects of structure
  1. Declaration of structure
  2. Accessing of structure's elements.
Declaring a structure

The following statement declares the structure type,

struct struct_name {
structure element 1;
structure element 2;
.....................
}

Once the new structure data type has been defined, one or more variables can be declared to be of that type. It makes available space to hold all the elements in the structure. in this case, 7 bytes. one for name, 4 for price and 2 for pages. These bytes are always in adjacent memory locations. Like variables, arrays structure variables can also be initialized in the following way:

struct book b1 = {"Basic C", 130.00, 234};

Accessing structure elements

Having declared the structure type and the structure variables, let us see how the elements of the structure can be accessed. Structure use a dot(.) operator to access their elements like b1.pages, b2.price etc. Whatever be the elements of the structure, they are always stored in contiguous memory locations.

Array of Structure

In our sample program, to store data of 100 books we would be required to use 100 different structure variables from b1 to b100, which is definitely not very convenient, thats why we go for array of structures.
====================================================================
main()
{
struct book
{
char name;
float price;
int pages;
} b[100];
====================================================================
Features of Structure

The values of a structure variable can be assigned to another structure variable of the same type using the assignment operator. For example,
====================================================================
struct employee e1 = {"Suresh", 27, "San diego"};
struct employee e2, e3;

strcpy (e2.name, e1.name);
e2.age = e1.age;


/* copying all elements */

e3 = e2;

printf("%s %d %s\n", e1.name, e1.age, e1.place);
printf("%s %d %s\n", e2.name, e2.age, e2.place);
printf("%s %d %s\n", e3.name, e3.age, e3.place);
====================================================================
C doesn't allow assigning the contents of one array to another by just equating the two. As we saw in the previous topic, for copying arrays we have to copy the contents of the array element by element. This copying of all structure element at one go has been possible only because the structure elements are stored in contiguous memory locations.One structure can be nested in another structure.
====================================================================
main()
{
struct address
{
char phone[15];
char city[10];
};

struct emp
{
char name[10];
struct address a;
};
struct emp e = {"Suresh", "12345", "Tenkasi"};

printf("My name is %s\n", e.name);
printf("My phone number is %s\n", e.a.phone);
printf("My native place is %s\n", e.a.city);
}
====================================================================
Like an ordinary variable, we can also pass the structure variable into the function either pass individual structure elements or the entire structure at one go.

Structure pointer

The way we can have a pointer pointing to an integer, similarly we can have a pointer pointing to a structure. Such pointers are known as "Structure Pointers".

Let us have a look at the following program which demonstrates the usage of a SP.
====================================================================
main()
{
struct book
{
char name[40];
char author[25]
};

struct book b1 = {"VLSI Design", "CS"};

struct book *ptr;

ptr = &b1;
printf("%s %s\n", ptr->name, ptr->author);
}
====================================================================
we can't use ptr.name, because ptr is not a structure variable it is pointer to a structure, and the dot operator requires a structure variable on its left. In such cases, C provides an operator ->, called an "arrow operator" to refer to the structure element.

Uses of Structures

Structures are useful in Database management, that is, to maintain data about employees in an organization, books in library, items in a store etc.

What is the difference b/w Structures and Unions?

Unions are like structures except they use less memory. If you create a structure with a double that is 8 bytes and an integer that is 4 bytes then the total size will still only be 8 bytes. This is because they are on top of each other. If you change the value of the double then the value of the integer will change and if you change the value of the integer then the value of the double will change.

Questions

What is a structure?
What are the differences between structures and arrays?
What is difference between Structure and Unions?
What is the similarity between a Structure, Union and enumeration?
Can a Structure contain a Pointer to itself?
How can we check whether the contents of two structure variables are same or not?
How would you use qsort() function to sort an array of structures?
What is the difference between class and structure?


Sunday, February 24, 2008

C Pointers and Arrays

POINTERS

Pointers are core to the C programming language. They allow us to access memory directly, which lets us write very efficient and thus very fast programs. Most modern programming languages have some form of pointers, and pointers are probably one of the most difficult concepts to master in C.

So, what is a pointer? Basically, it's an address in memory somewhere. We don't know where, and we don't need to know where. That's why we have the pointer. What do we use pointers for? Pointers are one of the most useful concepts in C. The reason is that pointers allow us to keep a single copy of a variable (i.e. the memory we are using) and change that memory from anywhere in the program. This may sound like a bad idea, and in practice, it's a difficult thing to control, but once mastered, you will realize why C is the default standard language for building most any real program today.

ARRAYS

The C language provides a capability that enables the user to design a set of similar data types called "Array". Ordinary variables are capable of holding one value at a time. However, there are situations in which we would want to store more than one value at a time in a single variable. For example, suppose we wish to arrange the percentage marks obtained by 100 students in a class in ascending order, constructing one variable(array variable) capable of storing all the 100 values. An Array is a collective name given to a group of similar quantities. These similar quantities could be all ints, all floats or all chars etc.

What is the connection b/w pointers and arrays in C?

A pointer is a tool used for keeping track of a certain spot in memory. In C, arrays are simply groups of similar data stored sequentially in memory. Because they are stored sequentially, we can keep track of the first item in an array with a pointer to that item, and use that as an index point for every other item in the array.

Usually, the array of characters is called a "string", whereas, an array of ints or floats is called an array. Remember that all elements of any array must be of a same type. So we can't have an array of 10 numbers in which 5 numbers are int and 5 numbers are float. In C we can define variable called marks, which represents not a single value of mark but a entire set of marks. Each element of the set can then be referenced by means of a number called as index number or subscript.

A simple program using an array:

let us try to write a program to find out the average marks obtained by 30 students.
=============================================================
main()
{
float avg, sum=0;
int i;
int marks[30]; /* array declaration*/
for(i=0; i<=29; i++) {
printf("Enter marks\n");
scanf("%d", &marks[i]); /* store data in array*/
}

for(i=0; i<=29; i++)
sum = sum+marks[i];

avg = sum/30;
printf("Average marks = %f\n", avg);
}
=============================================================
in int maks[30], int specifies the type of variable, marks specifies the name of a variable and the number 30 tells how many elements of the type int will be in our array. The bracket ([]) tells the compiler that we are dealing with an array.

Accessing elements of an array

All the array elements are numbered, starting with 0. Thus, marks[2] is not the second element of the array but the third. In our program we are using the variable i as a subscript to refer various elements of an array.

More on Arrays

The features which makes arrays so convenient to program would be discussed below.

Array initialization

How to initialize an array while declaring it? Following are few examples:

int num[6] = {1, 2, 3, 4, 5, 6};
int n[ ] = {2, 4, 6, 8, 10, 12};

Till the array elements are not given any specific values, they are supposed to contain the garbage values.

Array elements in memory

Consider the following array declaration. int arr[8]; It defines an array "arr" of size 8, that is, a block of 8 consecutive objects named arr[0], arr[1], ...,arr[7]. What happens in memory when we make this declaration? 16 bytes get immediately reserved in memory. As the storage class for this array is auto, the initial values for this array is garbage values. Whatever be the initial values, all the array elements would always be present in contiguous memory locations.

Bounds Checking

In C, there is no check to see if the subscript used for an array exceeds the size of the array. Data entered with a subscript exceeding the array size will simply be placed in memory outside the array. This will lead to unpredictable results.

Passing Array elements to a Function

Array elements can be passed to a function by calling the function by value or by reference. Consider the following program.
=============================================================
main()
{
int i;
int marks[ ] = {10, 20, 30, 40,50};

for (i=0; i<=4;i++)
display(marks[i]);
}

display(int m)
{
printf("%d\n", m);
}
=============================================================
Here we are passing an individual array element at a time to a function display() and getting it printed in the function display(). In call by reference, we are passing addressed of individual array elements to function display(). Hence the variable in which this address is collected is declared as a pointer variable.

Pointers and Arrays

Let's talk about pointers in general. A pointer is a number representing a memory address. We call it a pointer because it is pointing to a place in memory. Let's start by how to declare them.

int *ptr; // declares an integer pointer

basically a pointer is declared by putting * in front of a regular variable. Now let us see a simple program that explains the pointer.
=============================================================
main()
{
int i=3, *x;
float j=1.5, *y;
char k='c', *z;

printf("Value of i=%d\n", i);
printf("Value of j=%d\n", j);
printf("Value of k=%d\n", k);

x= &i; y=&j; z=&k;

printf("Original address in x=%u\n", x);
printf("Original address in y=%u\n", y);
printf("Original address in z=%u\n", z);

x++; y++; z++;

printf("New address in x=%u\n", x);
printf("New address in y=%u\n", y);
printf("New address in z=%u\n", z);
}
=============================================================

Suppose i,j and k are stored in memory at addresses 1002, 2004 and 5006, then the output would be;

Value of i=3
Value of j=1.5
Value of k=c
Original address in x = 1002
Original address in x = 2004
Original address in x = 5006
New address in x = 1004 // integer occupies 2 bytes
New address in y = 2008 // float occupies 4 bytes
New address in z = 5007 // character occupies 1 byte

The method of accessing array elements by using subscripted variables is already known to us. Next we will see accessing array elements by using pointers.
=============================================================
main()
{
int num[ ] = {1, 2, 3};
int i, *j;

j=&num[0];

for(i=0;i<=2;i++);
{
printf("Address = %u\n", j);
printf("Element = %d\n", *j);
j++;
}
}
=============================================================
Accessing array elements by pointers is always faster than accessing them by subscripts. However, array elements should be accessed using pointers if the elements are to be accessed in a fixed order. Instead, it would be easier to access the elements using a subscript if there is no fixed logic in accessing the elements.

Passing an entire array to a function

How to pass an entire array to a function rather than its individual elements. Consider the following example.
=============================================================
main()
{
int num[ ]={1, 2, 3};
display(&num[0], 3);
}
display(int *j, int n)
{
int i;
for(i=0; i<= n-1; i++)
{
printf("Element = %d\n", *j);
j++;
}
}
=============================================================
The Real Thing

int num[ ] = {1, 2, 3};
We know that on mentioning the name of the array, we get the base addresses. Thus, by saying *num we would be able to refer to the zeroth element of the array, that is, 1. One can easily say that *num and *(num+0) both refers the 0th element.
Similarly by saying *(num+1) we can refer the first element of the array, that is, 2. In fact, this is what the C compiler does internally. When we say, num[i], the C compiler internally converts it into *(num+i). This means that all the following notations are same.

num[i] == *(num+i) == *(i+num) == i[num]

More than One Dimension

It is also possible for arrays to have two or more dimensions. Consider the following program that stores roll numbers and marks obtained by a student side by side in a Matrix.
=============================================================
main()
{
int stud[4][2];
int i,j;
for (i=0; i<=3; i++)
{
printf("Enter the roll number and marks\n");
scanf("%d%d", &stud[i][0], &stud[i][1]);
}
for (i=0; i<=3; i++)
printf("%d %d\n", stud[i][0], stud[i][1]);
}
=============================================================
in stud[i][0] and stud[i][1] the first subscript of the variable stud, is row number which changes for every student. The second subscript tells which of the two columns we are talking about. The zeroth column which contains the roll number or the first column which contains the marks. Remember, the counting of rows and columns begin with zero.

Initializing a 2-D array

How do we initialize a two D arrays?

int stud[4][2] = { {1200, 56}, {1201, 45}, {1202, 87}, {1203, 66}};

While initializing an array it is necessary to mention the second column, whereas the first column is optional. Thus, the following declaration are perfectly acceptable.


int arr[2][3]={12,34,56, 23,54,67}; int arr[][3] ={12,34,56, 23,54,67} whereas

int arr[][]={12,34,56, 23,54,67}; int arr[2][] ={12,34,56, 23,54,67} would never work.

Questions

What are the differences between structures and arrays?
Difference between arrays and linked list?
What is the difference between Strings and Arrays?
Are the expressions arr and *arr same for an array of integers?
How would you dynamically allocate a one-dimensional and two-dimensional array of integers?
How can you increase the size of a dynamically allocated array?
How can you increase the size of a statically allocated array?

Reference

"Let Us C" by Yashavant Kanethar.