1. What are pointers? Specify the general form for declaring pointer variable(s) and list the pointer operators. A pointer is a variable that holds a memory address, i.e., the location of another variable in memory. A pointer declaration consists of a base type, an *, and the variable name. The general form for declaring a pointer variable is data-type *variable-name; Where data-type is the base type of the pointer. The name of the pointer variable is specified by variable-name. For example, int *p; Pointer operators: The pointer operators are & and *. The & is a unary operator that returns the memory address of its operand The * is a unary operator that returns the value located at the address that follows. 2. Briefly discuss on Pointer expressions – pointer assignments, pointer conversions, pointer Arithmetic and pointer comparisons. In general, expressions involving pointers conform to the same rules as other expressions. Pointer Assignments: A pointer on the right-hand side of an assignment statement can be used to assign its value to another pointer. For example, int x, *p1, *p2; p1 = &x; p2 = p1; Here, p1 and p2 both point to x. Thus both p1 and p2 refer to the same object. Pointer Conversions: One type of pointer can be converted into another type of pointer. There are two general categories of conversion: those that involve void * pointers and those that don’t. A void * pointer is called a generic pointer because it is permissible to assign to any other type of pointer. Pointer conversions can be performed by using an explicit cast. For example, double x = 100.1, *p1; int *p2; p1 = &x; p2 = (int *) p1; Pointer Arithmetic: There are only two arithmetic operations that can be used on pointers. They are addition and subtraction. For example, int *p1; p1++; p1--; /* let p1 contains the value 2000 */ /* after the expression, p1 contains 2002. Because int requires 2 bytes */ /* let p1 contains the value 2000 */ /* after the expression, p1 contains 1998. Because int requires 2 bytes */ We may add or subtract integers to or from pointers. The expression p1 = p1 + 12; makes p1 points to the 12th element of p1’s type beyond the one it currently points to. We can subtract one pointer from another in order to find the number of objects of their base type that separate the two. All other arithmetic operations are prohibited. We cannot multiply or divide pointers. We cannot add two pointers. We cannot apply the bitwise operators to them. We cannot add or subtract type float or double to or from pointers. Pointer Comparisons: We can compare two pointers in a relational expression. For example, let two pointers p and q. Then if ( p < q ) printf(“p points to lower memory than q”); Generally, pointer comparisons are useful only when two pointers point to a common object, such as an array. 3. Briefly discuss on C’s dynamic memory allocation and deallocation functions, multiple indirection and problems with pointers. C’s Dynamic memory allocation and deallocation functions: The region of free memory from which memory is allocated is called the heap. The prototypes for the dynamic allocation functions are in <stdlib.h> C defines four dynamic memory allocation and deallocation functions: malloc( ) The prototype of malloc( ) is void *malloc( int size); malloc( ) function returns a pointer to the first byte of a region of memory of size size that has been allocated from the heap. malloc( ) function returns a null pointer if there is insufficient memory in the heap. calloc( ) The prototype of calloc( ) is void *calloc( int num, int size); calloc( ) function allocates memory the size of which is equal to num * size. calloc( ) function allocates sufficient memory for an array of num objects of size size. All bits in the allocated memory are initially set to zero. calloc( ) function returns a pointer to the first byte of the allocated region. calloc( ) function returns null pointer if an error occurs. free( ) The prototype of free( ) is void free( void *ptr); free( ) function returns the memory pointed to by ptr to the heap. This makes the memory available for future allocation. free( ) function deallocates the memory pointed to by ptr which is allocated dynamically. realloc( ) The prototype of realloc( ) is void *realloc( void *ptr, int size ); realloc( ) function changes the size of the previously allocated memory pointed by ptr to that specified size. The value of size can be greater or less than the original. A pointer to the memory block is returned. The contents of the old block are copied into the new block up to size bytes. If there is not enough free memory in the heap to allocate size bytes, a null pointer is returned, and the original block is left unchanged. Mulitple indirection We can have a pointer point to another pointer that points to the target value. This situation is called multiple indirection or pointers to pointers. A variable that is a pointer to a pointer must be declared as such. We can do this by placing an additional asterisk in front of the variable name. For example, float **newbalance; To access the target value indirectly pointed to by a pointer to a pointer, we must apply the asterisk operator twice as printf(“%f”, **newbalance); The following program illustrates the multiple indirection or pointers to pointers In the above program, p is declared as a pointer to an integer and q as a pointer to a pointer to an integer. The call to printf( ) prints the number 10 on the screen Problems with pointers: Uninitialized pointer: In the following program, the value 10 is assigned to some unknown memory location. An error is caused by misunderstanding of the use of pointer: For example, In the above program, printf( ) does not print the value of x, which is 10, on the screen. It prints some unknown value because the assignment p = x; is wrong. That statement assigns the value 10 to the pointer p. However p is supposed to contain an address, not a value. 4. Briefly discuss on the relationship between pointers and arrays and how to declare arrays of pointers Pointers and Arrays: There is a close relationship between pointers and arrays. Consider the program fragment char str[80], *p1; p1 = str; /* is equivalent to p1 = &str[0]; */ Here, p1 has set to the address of the first array element in str. Name of the array points to the address of the first element of the array. To access the 5th element in str, str[4] Or *(p1+4) Both of the above statements will return the fifth element. Arrays always start at 0. C provides two methods of accessing array elements: pointer arithmetic and array indexing. Standard array-indexing notation is easier to understand, but pointer arithmetic can be faster. Arrays of pointers: Pointers can be arrayed like any other data type. The general form to declare array of pointers is data-type *array-name [size]; For example, the declaration of an int pointer array x of size 10 is int *x[10]; 5. What is a function? Specify the General form of a function Functions are the building blocks of C and the place where all program activity occurs. General form of a function ret-type fun-name ( parameter-list ) { body-of-function } The ret-type specifies the type of data that the function returns. A function may return any type of data except an array The parameter-list is a comma-separated list of variable names and their associated types. The parameters receive the values of the arguments when the function is called A function can be without parameters, in which case the parameter list is empty An empty parameter list can be explicitly specified as such by placing the keyword void inside the paranthesis The parameter declaration list for a function is of the form: fun-name (type1 var1, type2 var2, … , typeN varN ) 6. Briefly discuss on the scope of a function The scope rules of a language are the rules that govern whether a piece of code knows about or has access to another piece of code or data. The scope of a function is defined as follows: Each function is a discrete block of code A function defines a block scope A function code is private to that function and cannot be accessed by any statement in any other function except through a call to that function The code that constitutes the body of a function is hidden from the rest of the program and unless it uses global variables, it can neither affect nor be affected by other parts of the program. The code and data defined within one function cannot interact with the code and data defined in another function because the two functions have different scopes Variables that are defined within a function are local variables A local variable comes into existence when the function is entered and is destroyed upon exit A local variable cannot hold its value between function calls The local variable declared with static storage class specifier, the compiler treat the variable as if it were a global variable for storage purposes, but limit its scope to the function The formal parameters to a function also fall within the function’s scope A parameter is known throughout the entire function A parameter comes into existence when the function is called and is destroyed when the function is exited All functions have file scope. A function cannot be defined within another function. Thus C is not technically a block-structured language. 7. Explain the implementation of call by reference mechanism in C with pointers with suitable example In C, there are two ways that arguments can be passed to a function. They are 1. Call by value – This method copies the value of an argument / actual parameter into the formal parameter of the function. In this case, changes made to the parameter / formal parameter have no effect on the argument / actual parameter 2. Call by reference – In this method, the address of an argument / actual parameter is copied into the parameter / formal parameter. Inside the function, the address is used to access the actual parameter used in the call. It means that changes made to the parameter / formal parameter affect the argument / actual parameter. By default, C uses call by value mechanism. Call by reference is implemented with pointers, i.e., by passing a pointer to actual parameter instead of passing the actual parameter. Since the address of the actual parameter is passed to the function, code within the function can change the value of the actual parameter outside the function. For example, the following program demonstrates the implementation of call by reference mechanism in C with pointers In the above program, swap( ) function is able to exchange the values of the two variables pointed to by x and y because their addresses (not their values) are passed. Within the function, the contents of the variables are accessed using standard pointer operations, and their values are swapped. Here, swap ( ) is called with the addresses of the argurments / actual parameters. The output of the program is 8. Briefly discuss on various types of functions with appropriate return statements Functions are the building blocks of C and the place where all program activity occurs. All functions, except those of type void, have a value. The value is specified by the return statement. As long as function is not declared as void, we can use it as an operand in an expression A function call cannot be on the left-side of an expression. If so, the C compiler will flag it as an error and will not compile a program that contains it. Functions will be of three types. They are: 1. Functions may simply be computational – these functions are specifically designed to perform operations on their argurments and return a value based on that operation. A computational function is a purefunction. For example, sqrt( ) computes the square root of its arguments. 2. Functions that manipulates information and returns a value – these functions simply indicates the success or failure of that manipulation. For example, fclose( ) which closes a file associated with the file pointer. If the close operation is successful, the function returns 0 otherwise it returns EOF. 3. Functions that have no explicit return value – these functions are strictly procedural and produce no value. For example, exit( ) which terminates a program. All functions that do not return values should be declared as returning type void. Types of functions based on the return value and the number of parameters are: 1. void function with empty parameter-list The general form of void function with empty parameter-list is void fun-name ( ) { body-of-function [return;] } 2. void function with parameter-list The general form of void function with parameter-list is void fun-name ( parameter-list ) { body-of-function [return;] } 3. non-void function with empty parameter-list The general form of non-void function with empty parameter-list is ret-type fun-name ( ) { body-of-function return value; } 4. non-void function with parameter-list The general form of non-void function with parameter-list is ret-type fun-name ( parameter-list ) { body-of-function return value; } 9. What is the need of function prototypes? Specify the general form of a function prototype Function prototypes: In modern, properly written C programs, all functions must be declared before they are used. This is normally accomplished using a function prototype. Function prototypes enable the compiler to provide stronger type checking. The compiler can find and report any questionable type conversion between actual parameters and formal parameters when we use function prototypes. The compiler will also catch the differences between the number of actual parameters and formal parameters when we use function prototypes. The general form of a function prototype is ret-type fun-name ( type1 parameter-1, type2 parameter-2, ,,,,, typeN parameter-N); The use of parameter names is optional. However, they enable the compiler to identify any type mismatches by name when an error occurs. Hence it is recommended to include in the function prototypes. Function prototype is necessary when the function first use in the program is prior to the corresponding function definition. 10. Briefly discuss on structure, union, bit-field, enumeration and typedef Structure A structure is a collection of variables referenced under one name, providing a convenient means of keeping related information together. A structure declaration forms a template that can be used to create structure objects The variables that make up the structure are called members or fields or elements Usually, the members of a structure are logically related. The declaration of a structure should be terminated by a semicolon. Because a structure declaration is a statement. No variable is created with structure declaration. Structure declaration defines only an aggregate type not a variable. Until we declare a variable of that structure type, nothing is exist. The general form of a structure declaration is struct tag { type1 member-1; type2 member-2; ... typeN member-N; } structure-variables; Where either tag or structure-variables may be omitted, but not both. Declaring variables of the structure are struct structure-name variable-1, …, variable; Declaring pointers to structure are struct structure-name *ptr1, *ptr2; Declaring an array of the structure is struct structure-name array-name[size]; Accessing structure members: Individual members of a structure are accessed through the use of . (dot) operator through variable of structure. The general form for accessing a member of a structure though variable of structure is variable-name.member-name Individual members of a structure are accessed through the use of operator through pointer to the structure. The general form for accessing a member of a structure through pointer to that structure is pointer-to-structure member-name 11. Specify the function and prototypes of the following functions: printf( ) The function printf( ) performs formatted output function The prototype of printf( ) is int printf(const char *control-string…..); printf( ) function writes data to the console printf( ) function can operate on any of the built-in data types plus null-terminated character strings printf( ) function returns the number of characters written or a negative value if an error occurs. Control-string consists of two types of items. The first type is composed of characters that will be printed on the screen. The second type contains format specifiers that define the way the subsequent arguments are displayed. A format specifier begins with a percent sign and is followed by the format code. There must be exactly the same number of arguments as there are format specifiers and the format specifiers and the arguments are matched in order from left to right. scanf( ) The function scanf( ) performs formatted input function scanf( ) is the general purpose console input routine. The prototype of scanf( ) is int scanf( const char *control-string…….); scanf( ) function reads data from the keyboard. scanf( ) function returns the number of data items successfully assigned a value. scanf( ) function returns EOF if an error occurs. scanf( ) can read all the built-in data types and automatically convert numbers into the proper internal format Control-string determines how values are read into the variables pointed to in the argument list Control-string consists of three classifications of characters: 1. Format specifiers 2. White space characters 3. Non-white space characters Input format specifiers are preceded by a % sign and tell scanf( ) what type of data is to be read next The format specifiers are matched, in order from left to right with arguments in the argument list. fprintf( ) fprintf( ) function behaves exactly like printf( ) except that it operate with files The prototype of fprintf( ) is int fprintf(FILE *fp, const char *control_string, . . .); fp is a file pointer returned by a call to fopen( ) fprintf( ) function writes assorted or mixed data to the file associated with the file pointer fp fscanf( ) fscanf( ) function behaves exactly like scanf( ) except that it operate with files The prototype of fscanf( ) is int fscanf(FILE *fp, const char *control_string, . . .); fp is a file pointer returned by a call to fopen( ) fscanf( ) function reads assorted or mixed data from the file associated with the file pointer fp fread( ) fread( ) allows the reading of blocks of any type of data The prototype of fread( ) function is int fread(void *buffer, int num_bytes, int count, FILE *fp); buffer is a pointer to a region of memory that will receive the data from the file count specifies number of items that are to be read with each item being num_bytes in length fp is a file pointer to a previously opened stream fread( ) function returns the number of items read. This value may be less than count if the end of the file is reached or an error occurs fwrite( ) fwrite( ) allows the writing of blocks of any type of data The prototype of fwrite( ) function is int fwrite(const void *buffer, int num_bytes, int count, FILE *fp); buffer is a pointer to the information that will be written to the file count specifies number of items that are to be written with each item being num_bytes in length fp is a file pointer to a previously opened stream fwrite( ) function returns the number of items written. This value is equal to count unless an error occurs. fputs( ) The prototype of fputs( ) is int fputs(const char *str, FILE *fp); fputs( ) function write character string to the disk file fputs( ) function writes the string pointed to by str to the specified stream. fputs( ) function returns EOF if an error occurs. fgets( ) The prototype of fgets( ) is char *fgets(char *str, int length, FILE *fp); fgets( ) function read character strings from the disk file fgets( ) function reads a string from the specified stream until either a newline character is read or length - 1 characters have been read if a newline is read, it will be part of the string resultant string will be null-terminated fgets( ) function returns str if successful and a null pointer if an error occurs. fputc( ) or putc( ) fputc( ) function writes character to a file that was opened for writing using fopen( ) function The prototype of fputc( ) is int fputc(int ch, FILE *fp); fp is a file pointer of type FILE and is returned by fopen( ) ch is the character to be output The prototype of putc( ) is int putc(int ch, FILE *fp); fp is a file pointer of type FILE and is returned by fopen( ) ch is the character to be output fgetc( ) or getc( ) The prototype of fgetc( ) is int fgetc( FILE *fp); where fp is a file pointer of type FILE The prototype of getc( ) is int getc( FILE *fp); where fp is a file pointer of type FILE fgetc( ) function returns the next character from the specified input stream and increments the file position indicator. fgetc( ) returns EOF if the end of the file is reached fgetc( ) returns EOF if an error is encountered. getchar( ) The prototype of getchar( ) is int getchar( ); It is console input function to read a character from the keyboard getchar( ) function waits until a key is pressed and then returns its value. The key is also automatically echoed to the screen getchar( ) returns EOF if an error occurs. It is called line-buffered input. i.e., we have to press <ENTER> key before any character is returned. putchar( ) The prototype of putchar( ) is int putchar(int ch); It is console output function to write a character to the screen. putchar( ) function writes a character to the screen at the current cursor position putchar( ) returns the character written or EOF if an error occurs. getch( ) The prototype of getch( ) is int getch( ); The prototype of getch( ) is found in the header file <conio.h> getch( ) function waits for a keypress after which it returns immediately. getch( ) function does not echo the key pressed to the screen getche( ) The prototype of getche( ) is int getche( ); The prototype of getche( ) is found in the header file <conio.h> getche( ) function waits for a keypress after which it returns immediately getche( ) function echoes the key pressed to the screen gets( ) The prototype of gets( ) is char *gets(char *str); gets( ) function reads a string of characters entered at the keyboard until we press carriage return and stores them at the address pointed to by its argument. Carriage return does not become part of the string; instead, a null terminator is placed at the end. gets( ) also returns str. puts( ) The prototype of puts( ) is int puts( const char *str); puts( ) function writes its string argument to the screen followed by a newline. puts( ) can only output a string of characters – it cannot output numbers or do format conversions puts( ) function returns a non-negative value if successful or EOF if an error occurs. fopen( ) fopen( ) function opens a stream for use and links a file with that stream fopen( ) function returns the file pointer associated with that file. The prototype of fopen( ) is FILE *fopen(const char *filename, const char *mode); filename is a pointer to a string of characters that make up a valid filename and may include path The string pointed to by mode determines how the file will be opened fclose( ) The prototype of fclose( ) is int fclose( FILE *fp ); where fp is a file pointer of type FILE fclose( ) function closes the file associated with stream and flushes its buffer. After a call to fclose( ), stream is no longer connected with the file, and any automatically allocated buffers are deallocated. feof( ) The prototype of feof( ) is int feof( FILE *fp); where fp is a file pointer of type FILE feof( ) function determines whether the end of the file associated with stream has been reached. A non-zero is returned if the file position indicator is at the end of the file Otherwise zero is returned. fseek( ) fseek( ) function sets the file position indicator to perform random read and write operations fseek( ) function returns zero when successful and a non-zero value if an error occurs. The prototype of fseek( ) is int fseek( FILE *fp, long int numbytes, int origin); fp is a file pointer returned by a call to fopen( ) numbytes is the number of bytes from origin, which will become the new current position origin is one of the following macros: origin Macro Name Beginning of file SEEK_SET Current position SEEK_CUR End of file SEEK_END ftell( ) ftell( ) function determines the current location of a file The prototype of ftell( ) is long int ftell( FILE *fp); ftell( ) function returns the location of the current position of the file associated with fp ftell( ) function returns -1 if a failure occurs. ferror( ) The prototype of ferror( ) is int ferror( FILE *fp); where fp is a file pointer of type FILE ferror( ) function checks for a file error on the given stream ferror( ) returns zero if no error is occurred ferror( ) returns a non-zero if an error is occurred.