Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
(Order of Presentation: History,Definition,Usage,Syntax,Initialization,Declaration,Assignmet,Accessing, Functions, Inter Function Communication, Complex Functions, Applications, Examples)
Pointers:
Pointers are one of the derived types in C. One of the powerful tool and easy to use once they are mastered. Some of the advantages of pointers are listed below: A pointer enables us to access a variable that is defined outside the function. Pointers are more efficient in handling the data tables. Pointers reduce the length and complexity of a program. The use of a pointer array to character strings save data storage space in memory. The real power of C lies in the proper use of pointers.
Pointer Concepts:
The basic data types in C are int, float, char double and void. Pointer is a special data type which is derived from these basic data types. There are three concepts associated with the pointers are, Pointer Constants Pointer Values Pointer Variables
Pointer Constant:
As we know, computers use their memory for storing the instructions of a program, as well as the values of the variables that are associated with it. The computers memory is a sequential collection of storage cells. Each cell can hold one byte of information, has a unique number associated with it called as address. The computer addresses are numbered consecutively, starting from zero. The last address depends on the memory size. Let us assume the size of the memory is 64K then, The total memory locations = 64K = 64 * 1K = 64 * 1024 bytes = 65536 bytes (locations) So, here the last address is 65535(started with 0). Physically they are divided into even bank and odd bank. Even bank is set of memory locations with even addresses. Like 0, 2, 4, 665534. Odd bank is set of memory locations with odd addresses. Like 1, 3, 5 .65535.
These memory addresses are called pointer constants. We cannot change them, but we can only use them to store data values. For example, in the above memory organization, the addresses ranging from 0 to 65535 are known as pointer constants. Remember one thing, the address of a memory location is a pointer constant and cannot be changed .
Pointer Value:
Whenever we declare a variable, the system allocates , an appropriate location to hold the value of the variable somewhere in the memory,. Consider the following declaration, int i=10; This declaration tells the C compiler to perform the following activities: Reserve space in the memory to hold the integer value. Associate the name i with this memory location. Store the value 10 at this location. We can represent is location in the memory by the following memory map:
Memory is divided into number of storage cells called locations. Out of these the addresses, the system assigns some addresses of the memory locations to the variables. These memory locations assigned to the variables by the system are called pointer values. For example, the address 65510 which is assigned to the variable i is a pointer value.
Pointer Assignment :
The assignment operation (=) between two pointers makes them point to the same pointee. The example below adds a second pointer, second, assigned with the statement second = numPtr;.The result is that second points to the same pointee as numPtr. In the drawing, this means that the second and numPtr boxes both contain arrows pointing to num. Assignment between pointers does not change or even touch the pointers. It just changes which pointers a pointer refers to.
After assignment, the == test comparing the two pointers will return true. For example (second==numPtr) above is true.
Pointer Variables :
Pointer variables are declared just like any other variable. The declaration gives the typeand name of the new variable and reserves memory to hold its value. The declaration does not assign a pointee for the pointer int* numPtr; // Declare the int* (pointer to int) variable "numPtr". // This allocates space for the pointer, but not the pointee.
The & Operator: The unary or monadic operator & gives the ``address of a variable''.
The address of the variable cannot be accessed directly. The address can be obtained by using address operator(&) in C language. The address operator can be used with any variable that can be placed on the left side of an assignment operator. The format specifier of address is %u(unsigned integer),the reason is addresses are always positive values. We can also use %x to know the address of a variable. Example, to know the address of variable n, just use &n. Note: Constants, expressions, and array name cannot be placed on the left side of the assignment and hence accessing address is invalid for constants, array names and expressions.
Pointer Variable:
A variable Which holds the address of some other variable is called pointer variable. A pointer variable should contain always the address only.
The * Operator: The indirection or dereference operator * gives the ``contents of an object pointed to by a pointer''.
It is called as Value at address operator. It returns the value stored at a particular address. It is also Known as Indirection or Dereferencing Operator
data type
*ptr_name;
The syntax for declaring a pointer variable is as follows, This tells the compiler three things about the variable ptr_name.
1. The asterisk(*) tells that the variable ptr_name is a pointer variable. 2. ptr_name needs a memory location. 3. ptr_name points to a variable of type data type. For example, int *pi; declares the variable p as a pointer variable that points to an integer data type. Remember that the type int refers to the data type of the variable being pointed by pi.
Initializing Pointers:
Once a pointer variable has been declared, it can be made to point to a variable using statement such as
ptr_name=&var;
Which cause ptr_name to point to var.Now ptr_name contains the address of var. This is known as pointer initialization. Before a pointer is initialized it should not be used.
*ptr_name
Example1
The above program illustrates how to access the variable using pointers. After finding the first statement i=10 ,the compiler creates a variable i with a value of 10 at a memory location. Then coming to line 2 and 3 a pointer variable pi is create and initialized with the address of the i variable. then the compiler automatically provides a link between these two variables as follows.
pi
10 8342
8342 8338
Note: Pointer variable always points to a address of the another variable .Following statements are not valid with respect to pointers. int i=10, k, *pi=&i; k=pi; // pointer value cannot be accessed by integer pi=65506(constant); // we cannot directly assign a value to a pointer variable
Memory model:
In c there are six type of memory model. If you want to see all memory model in Turbo C++ IDE then open Turbo C++ IDE and the go: Options menu -> Compiler -> Code generation These memory models are: (a) TINY (b) SMALL (c) MEDIUM (d) COMPACT (e) LARGE (f) HUGE
If you want to change the memory model then go to: Options menu -> Compiler -> Code generation And select any memory model and click OK button.
Properties of memory mode in C: (1) Memory model decides the default type of pointer in C. Note: Code: A pointer to function is called code., Data: A pointer to variable is called data.
Types of Pointers:
In TURBO C there are three types of pointers. TURBO C works under DOS operating system which is based on 8085 microprocessor. 1. Near pointer 2. Far pointer 3. Huge pointer
Near pointer:
The pointer which can points only 64KB data segment or segment number 8 is known as near pointer. That is near pointer cannot access beyond the data segment like graphics video memory, text video memory etc. Size of near pointer is two byte. With help keyword near, we can make any pointer as near pointer.
Far pointer :
The pointer which can point or access whole the residence memory of RAM i.e. which can access all 16 segments is known as far pointer. Size of far pointer is 4 byte or 32 bit.
Huge pointer:
The pointer which can point or access whole the residence memory of RAM i.e. which can access all the 16 segments is known as huge pointer. Size of huge pointer is 4 byte or 32 bit.
NULL pointer:
Literal meaning of NULL pointer is a pointer which is pointing to nothing. NULL pointer points the base address of segment. Examples of NULL pointer:
1. int *ptr=(char *)0; 2. float *ptr=(float *)0; 3. char *ptr=(char *)0; 4. double *ptr=(double *)0; 5. char *ptr=\0; 6. int *ptr=NULL;
What is meaning of NULL? NULL is macro constant which has been defined in the heard file stdio.h, alloc.h, mem.h, stddef.h and stdlib.h as #define NULL 0 Wild pointer: A pointer in c which has not been initialized is known as wild pointer. Generic pointer: void pointer in c is known as generic pointer. Literal meaning of generic pointer is a pointer which can point type of data. Example: void *ptr; Here ptr is generic pointer. Important points about generic pointer in c? 1. We cannot dereference generic pointer. Dangling Pointer:
Pointer pointing to a destroyed variable. it usually happen during dynamic memory allocation when the object is destroyed but not free and the pointer is still pointing to the destroy object. For example, consider the following declaration, int *pi; This declaration indicates that pi is a pointer variable and the corresponding memory location should contain address of an integer variable. But , the declaration will not initialize the memory location and memory contains garbage value as shown in below.
pi
Garbage Value
Note: We cannot use a pointer variable to the register variable. The reason is that, user does not know the address of the register variable. So we are not able to use pointer variable on register variables.
Pointer arithmetic:
Pointers can be added and subtracted. Addition and subtraction are mainly for moving forward and backward in an array. operations that cannot be performed on pointer 1. Addition of two addresses. 2. Multiplying two addresses. 3. Division of two addresses. 4. Modulo operation on pointer. 5. Cannot perform bitwise AND,OR,XOR operations on pointer. 6. Cannot perform NOT operation or negation operation. Operator ++ -Result Goes to the next memory location that the pointer is pointing to. Goes to the previous memory location that the pointer is pointing to. Subtracts value from pointer. Adding to the pointer
-= or += or +
The following operations can be performed on a pointer: Addition of a number to a pointer. Pointer can be incremented to point to the next locations. Example: int i=4 ,pi=&i; //(assume address of i=1000) float j,*pj=&j;// (assume address of j=2000) pi = pi + 1; // here pi incremented by (1*data type times) pi = pi + 9; // pi = 1000 + (9*2) 1018 address pj = pj + 3; // pj=1018+(3*4)1030 address
Subtraction of a number from a pointer. Pointer can be decremented to point to the earlier locations. Example: int i=4,*pi=&i; //assume address of i =1000) char c, *pc=&c; // assume address of c = 2000 double d, *pd=&d; // assume address of d=3000 pi = pi-2; /* pi=1000-(2*2)=996 address */ pc = pc-5; /* pc=2000-(5*1)=1985 address pd = pd-6; /* pd=3000-(6*8)=2952 address */ Pointer variables may be subtracted from one another. This is helpful while finding array boundaries. Be careful while performing subtraction of two pointers. Pointer variables can be used in comparisons, but usually only in a comparison to NULL. We can also use increment/decrement operators with pointers this is performed same as adding/subtraction of integer to/from pointer. The following operations cannot be performed on pointers. Addition of two pointers addresses. Multiplication of a pointer with a constant, two pointers. Division of a pointer with a constant, two pointers. Address + Address = Illegal Address * Address = Illegal Address / Address = Illegal Address % Address = Illegal Address & Address = Illegal Address | Address = Illegal Address ^ Address = Illegal ~Address = Illegal
Explanation :
Two Pointers of different data types can be compared . In the above program we have compared two pointers of different data types. It is perfectly legal in C Programming. As we know Pointers can store Address of any data type, address of the data type is Integer so we can compare address of any two pointers although they are of different data types.
Pointer Expressions:
Like other variables, pointer variables can be used in expressions. For example, if p1 and p2 are two valid pointers ,then the following statements are valid. a= *p1 + *p2; sum = sum + *p1; z = 10 / *p2; f = *p1 * i;
Note: be careful while writing pointer expressions .The expression *p++ will result in the increment of the address of p by data type times and points to the new value. Whereas the expression (*p) ++ will increments the vale at the address. If you are not properly coded you will get some unwanted result.
Example, for the above array we can have the following statement, int *ptr=a; (or) int *ptr=&a[0]; To refer the array elements by using pointer the following notations are used.
1
1000 ptr 1002
2
1004
3
1006 1008
5
address
values
base address
The above program illustrates displaying the array elements using pointers. Note: Note that the array name num is a constant pointer points to the base address, then the increment of its value is illegal, num++ is invalid. (Just like other variables, we have to declare pointers before we can use them. Pointer declarations look much like other declarations. When pointers are declared, the keyword at the beginning (c int, char and so on) declares the type of variable that the pointer will point to. The pointer itself is not of that type, it is of type pointer to that type. A given pointer only points to one particular type, not to all possible types. Here's the declaration of an array and a pointer: int ar[5], *ip; The * in front of ip in the declaration shows that it is a pointer, not an ordinary variable. It is of type pointer to int, and can only be used to refer to variables of type int. It's still uninitialized; it has to be made to point to something. int ar[5], *ip; ip = &ar[3]; In the example, the pointer is made to point to the member of the array ar whose index is 3, i.e. the fourth member. we can assign values to pointers just like ordinary variables; the difference is simply in what the value means. Example: Array and pointer arithmetic Sample Code : 1. #include <stdio.h> 2. int main() 3. { 4. int ArrayA[3]={1,2,3}; 5. int *ptr; 6. ptr=ArrayA; 7. printf("address: %p - array value:%d n",ptr,*ptr); 8. ptr++; 9. printf("address: %p - array value:%d n",ptr,*ptr); 10. return 0; 11. }
Description : In line 1 we are declaring ArrayA integer array variable initialized to numbers 1,2,3, in line 2, the pointer variable ptr is declared. In line 3, the address of variable ArrayA is assigned to variable ptr. In line 5 ptr is incremented by 1. Note: & notation should not be used with arrays because arrays identifier is pointer to the first element of the array.) Pointers And Two Dimensional Arrays
A two dimensional array is an array of one dimensional arrays. The important thing to notice about twodimensional array is that, just as in a one-dimensional array, the name of the array is a pointer constant the first element of the array, however in 2-D array, the first element is another array. Let us consider we have a two-dimensional array of integers. When we dereference the array name, we dont get one integer, we get an array on integers. In other words the dereference of the array name of a two-dimensional array is a pointer to a one-dimensional array. Here we require two indirections to refer the elements Let us take the declaration int a [3][4]; Then following notations are used to refer the two-dimensional array elements,
a a+i
*(a+i) -----> points to first element in the ith row *(a+i) +j -----> points to jth element in the ith row
Example:
*(*(*(a+i) +j) +k) --> value stored at kth dimension ith row jth column
Example
2. int main() 3. { 4. char a='b'; 5. char *ptr; 6. printf("%cn",a); 7. ptr=&a; 8. printf("%pn",ptr); 9. *ptr='d'; 10. printf("%cn",a); 11. return 0; 12. } Output : b 001423 D Description: In line 1 we are declaring char variable called a; it is initialized to character b, in line 2, the pointer variable ptr is declared. In line 4, the address of variable a is assigned to variable ptr. In line 6 value stored at the memory address that ptr points to is changed to d Note: & notation means address-of operand in this case &a means address-of a.
Observe the following points when the program is executed, The address of actual parameters a and b are copied into formal parameters pa and pb. In the function header of swap (), the variables a and b are declared as pointer variables. The values of a and b accessed and changed using pointer variables pa and pb. Pointer to Function: (Function Returning Pointers) The way function return an int, float and char, it can return a pointer. To make a function return a pointer it has to be explicitly mentioned in the calling function as well as in the function declaration. Three things should be done to avail the feature of functions return pointer. 1. Declaration of function returning pointer 2. Declaring pointer and assigning function call 3. Defining function returning pointer Syntax for declaration of function returning pointer
After executing above statement ptr consisting of the address that is returned by the function. Remember the return type of the function and pointer type should match here. The function Definition returning pointer takes of the form, return_type *function_name (arguments) { // local declarations // executable statements return (&variable); Here dont forget to send address with return statement. } Example:
The execution of the program as follows, Execution of the program starts at main. Two variables and b are created and initialized at run-time. A pointer variable is created and initialized with the return value of the function max (). Once the control is transferred from function main () to max (), it got executed and returns the pointer value to main(). Here we are having the address of the maximum variable address to display it just use indirection operator (*). Note: function return pointer does not have any advantage except in the handling of strings.
Pointers To Pointers :
It is possible to make a pointer to point to another pointer variable. But the pointer must be of a type that allows it to point to a pointer. A variable which contains the address of a pointer variable is known as pointer to pointer. Its major application is in referring the elements of the two dimensional array. Syntax for declaring pointer to pointer,
data type **ptr_ptr; This declaration tells compiler to allocate a memory for the variable ptr_ptr in which address of a pointer variable which points to value of type data type can be stored. Syntax for initialization ptr_ptr=&ptr_name; This initialization tells the compiler that now ptr_ptr points to the address of a pointer variable. Accessing the element value,
**ptr_ptr;
It is equalent to *(*(&ptr_name));
The above program illustrates the use of pointers to pointers. Here, using two indirection operators the data item 16 can be accessed (i.e., *ppi refers to pi and **ppi refers to i).
No cast is needed to assign an address to a void * or from a void * to another pointer type. Where as a pointer to void can not be deferenced unless it is cast.
void * void
A void pointer is a C convention for a raw address. The compiler has no idea what type of object a void Pointer really points to. If we write int *ip; ip points to an int. If we write void *p; p doesnt point to a void! In C , any time we need a void pointer, we can use another pointer type. For example, if you have a char*, we can pass it to a function that expects a void*. we dont even need to cast it. In C , we can use a void* any time you need any kind of pointer, without casting. A void pointer is used for working with raw memory or for passing a pointer to an unspecified type. Some C code operates on raw memory. When C was first invented, character pointers (char *) were used for that. Then people started getting confused about when a character pointer was a string, when it was a character array, and when it was raw memory.
Example:
printf (%d,*((int*)G)); /* Now it will display 101 float *P = G; /* No warning, still not safe */ printf (%f,*((float*)G)); /* Now it will display 98.45 Example: #include <stdio.h> void use_int(void *); void use_float(void *); void greeting(void (*)(void *), void *); int main(void) { char ans; int i_age = 22; float f_age = 22.0; void *p; printf("Use int (i) or float (f)? "); scanf("%c", &ans); if (ans == 'i') { p = &i_age; greeting(use_int, p);
} else { p = &f_age; greeting(use_float, p); } return 0; } void greeting(void (*fp)(void *), void *q) { fp(q); } void use_int(void *r) { int a; a = * (int *) r; printf("As an integer, you are %d years old.\n", a); } void use_float(void *s) { float *b; b = (float *) s; printf("As a float, you are %f years old.\n", *b); } Although this requires us to cast the void pointer into the appropriate type in the relevant subroutine (use_int or use_float), the flexibility here appears in the greeting routine, which can now handle in principle a function with any type of argument.
Pointer Compatibility:
We should not store the address of a data variable of one type into a pointer variable of another type. During assigning we should see that the type of data variable and type of the pointer variable should be same or compatible. Other wise it will result in unwanted output. The following program segment is wrong, int i=10; float *pf; pf=&i; // data variable is integer and pointer variable is float It is possible to use incompatible pointer types while assigning with type casting pointer. Able to exist and perform in harmonious or agreeable combination
Two pointer types with the same type qualifiers are compatible if they point to objects of compatible types. The composite type for two compatible pointer types is the similarly qualified pointer to the composite type The following example shows compatible declarations for the assignment operation: float subtotal; float * sub_ptr; /* ... */ sub_ptr = &subtotal; printf("The subtotal is %f\n", *sub_ptr); The next example shows incompatible declarations for the assignment operation: double league; int * minor; /* ... */ minor = &league; /* error */
Casting Pointers:
When assigning a memory address of a variable of one type to a pointer that points to another type it is best to use the cast operator to indicate the cast is intentional (this will remove the warning). Example: int V = 101; float *P = (float *) &V; /* Casts int address to float * */ Removes warning, but is still a somewhat unsafe thing to do.
Array of Pointers :
A pointer is a variable that contains the memory location of another variable. The values you assign to the pointers are memory addresses of other variables (or other pointers). A running program gets a certain space in the main memory. Syntax of declaring a pointer: data_type_name * variable name Specify the data type of data stored in the location, which is to be identified by the pointer. The asterisk tells the compiler that we are creating a pointer variable. Then specify the name of variable. Example: #include <stdio.h> #include <conio.h> main() { clrscr(); int *array[3]; int x = 10, y = 20, z = 30; int i;
array[0] = &x; array[1] = &y; array[2] = &z; for (i=0; i< 3; i++) { printf("The value of %d= %d ,address is %u\t \n", i, *(array[i]), array[i]); } getch(); return 0; } Output: The value of 0 = 10, address is 65518 The value of 1 = 20, address is 65516 The value of 2 = 30, address is 65514 A pointer variable always contains an address; an array of pointers would be nothing but a collection of addresses. The addresses present in the array of pointers can be addresses of variables or addresses of array elements or any other addresses. The major application of this is in handling data tables efficiently and table of strings. All rules that apply to an ordinary array apply to the array of pointes as well. The Syntax for declaration of array of pointers as follows, data type *arr_ptr [size]; This declaration tells the compiler arr_ptr is an array of addresses, pointing to the values of data type. Then initialization can be done same as array element initialization. Example arr_ptr [3] =&var, will initialize 3rd element of the array with the address of var. The dereferencing operator is used as follows *(arr_ptr [index]) --> will give the value at particular address. Look at the following code array of pointers to ordinary Variables
The above figure shows contents and the arrangement of the array of pointers in memory. Here, arr contains the addresses of int variables i, j, k and l. The for loop is used to print the values present at these addresses. A two-dimensional array can be represented using pointer to an array. But, a two-dimensional array can be expressed in terms of array of pointers also. Using array of pointers a two dimensional array can be defined as, data type *arr_ptr [size]; where data type refers to the data type of the array. arr_ptr refers to the name of the array and size is the maximum number of elements in the row. Example int *arr [3]; Here, p is an array of pointers, and then following notations are used to refer elements. p [i] --> points the address of the element ith row,
p[i] +j --> points the address of the element ith row and jth column *(p[i] +j) --> value at ith row and jth column.
Pointers To Functions:
Pointer to a function (also known as function pointer) is a very powerful feature of C. Function pointer provides efficient and elegant programming technique. Function pointers are less error prone than normal pointers since we will never allocate or de-allocate memory for the functions. Every variable with the exception of register has an address. We have seen how we can refer variables of type char, int and float. Through their addresses, by using pointers. Functions exist in memory just like variables. C will allow you to define pointers to functions. Just like variables, a function name gives the starting address of function stored in memory. The below code illustrate how to get the address of a function.
f_ptr=function_name;
After this assignment we need to call the function, the syntax associated with the function call is as follows,
(*f_ptr)(arguments);
This is another way of calling the function. There are no changes in the declaration of the function body. The below program simulates a simple calculator using function pointers.
Example: // illustrates displaying characters using pointer #include<stdio.h> void main () { char s [] =hello; char *ptr; ptr=s; while (*ptr! =\0) { printf ( %c,*ptr); ptr++; } }
OUTPUT hello
// C program illustrates Command Line Arguments #include<stdio.h> int main (int argc, char *argv []) { int j; printf (The name of the program is %s, argv[0]); printf (The total number of arguments are: %d, argc); for (j=1; j<=argc; j++) printf (\n argument %d is %s, j, argv[j]); return 0; }
OUTPUT:
C:\tc\bin\>test one two three The name of the program is test The total number of arguments are:4 argument 1 is one argument 2 is two
argument 3 is three
1. malloc This is the most commonly used method. Simply pass in how big you want your memory to be (in bytes), and you get a pointer to that memory back. The memory is uninitialized. If it fails it returns NULL. malloc()function allocate a block of byte of memory in byte. In this when the memory block needed explicitly requested. The malloc() function is same as a function is request for RAM in the system memory. If the request is grant then a void pointer return and the pointer point start of that block. If the request fail then a NULL pointer return. Example: malloc( number of element * size of each element); int * ptr; ptr = malloc(10*sizeof(int)); Where size represents the memory required in bytes .The memory which is provided is contiguous memory. But malloc function return void pointer so it needed type casting of that pointer. Examlpe: (type cast)malloc( number of element * size of each element); int * ptr; ptr =(int*) malloc(10*sizeof(int)); similarly for allocation of memory to a structure variable : Examlpe: (struct name)malloc( sizeof(struct name)); struct employee { int emp_id; char emp_name[20]; float emp_contact_no; }; struct employee *ptr ptr=(struct employee*)malloc(sizeof(struct employee));
2. calloc Instead of passing in a size, you tell calloc how many of a certain type of variable you are going to use. E.g. 10 ints, or 16 structs. The memory is initialized to zeros. If it fails it returns NULL.
In malloc requested memory is provided a block of contiguous memory . calloc() function is similar to the malloc rather then calloc() function allocated the memory block for an array of elements. Memory for a group of objects used calloc() function. If calloc() function is executed succesfully then its allocated memory is set as zero and a pointer returned and if the function failed then a NULL pointer return. Example: void *calloc(size_t number,size_t size); size_t used for unsigned on most compilers.The number is the number of allocate, and size is the size (in bytes) of each object. int main () { int number,i; printf("Enter the number "); scanf("%d",&number); printf("Number which is here are",number); int *ptr = (int *) calloc (number,sizeof(int)); for (i=0; i<number;i++) { ptr[i] = i +i; } for (i=0; i<number;i++) { printf("Result is %d %d\n",i,ptr[i]); } } 3. realloc This method resizes an existing block of memory and you can make your existing memory allocation bigger or smaller. It frees the existing block and returns a void* to the new block. If you pass in zero, it effectively frees the memory in question. If it fails it returns NULL (see the comments in the code below for why you should pay careful attention to how you use realloc). realloc() function is used for resize the size of memory block which is allocated by the malloc() and calloc () function. objects which is
#include <stdlib.h> void *realloc (Pointer, Size) void *Pointer; size_t Size;
Two situation where use realloc() function. When allocated block is insufficient need more memory then use realloc(). When allocated memory is much more then the required application then use realloc(). Example: realloc(ptr, new size); /* Through realloc() resize the memory . */ #include <stdio.h> #include <stdlib.h> #include <string.h> { char buffer[80], *msg; /* Input a string. */ puts("Enter the text line"); gets(buffer); /* The string copied in to initial allocated block */ msg = realloc(NULL, strlen(buffur)+1); strcpy(msg, buffer); /* Display the message which copied. */ puts(message); /* Get another string from the user. */ puts("Enter another text line."); ; gets(buffer); /* Resize the memory and also concatenate the string to it. */ msg = realloc(msg,(strlen(msg) + strlen(buffer)+1)); strcat(msg, buffer); } 4. free(): #include <stdlib.h> void free (Pointer) void * Pointer; You call free, nice and easy, and your memory is released (although it is not deleted as such the data may exist until something else overwrites it, or part of it, or until the program ends). For deallocation of the memory which is allocated through the malloc() function and calloc() function used free() function. Example: free(ptr);
int main () { int number,i; printf("Enter the number "); scanf("%d",&number); printf("Number which is here are",number); for (i=0; i<number;i++) { ptr[i] = i +i; } for (i=0; i<number;i++) { printf("Result is %d %d\n",i,ptr[i]); } free(ptr); }
Example that uses all four methods so you can see them at work: #include <stdlib.h> #define BIG_NUMBER 1024 #define SMALL_NUMBER 16 struct msg { int code; char message[BIG_NUMBER]; }; int main(void) { char* buffer; struct msg* messagelist; /* Allocate some memory from the heap */ buffer = (char*)malloc(BIG_NUMBER); if (buffer != NULL) { /* I can use the memory safely */ } /* Reduce the size of the memory */ char* smallbuffer = (char*)realloc(buffer, SMALL_NUMBER); if (smallbuffer != NULL) {
/* I can use the memory safely */ } /******************************************* * NOTE: Look carefully at the realloc call above. * If the call to realloc had failed and I had assigned * it to the original buffer like so: * buffer = (char*)realloc(buffer, SMALL_NUMBER); * then my buffer would have been set to NULL and I would * not only lose access to the data that was stored * there, but I'd create a memory leak too! *******************************************/ /* Allocate some memory from the heap */ messagelist = (struct msg*)calloc(SMALL_NUMBER, sizeof(struct msg)); if (messagelist != NULL) { /* I can use the memory safely */ } /* Remember to clear up after myself */ free(smallbuffer); free(messagelist); /* NOTE: I DON'T need to free the 'buffer' variable */ /* because realloc already did it for me :-) */ return EXIT_SUCCESS; } Synopsis of functions: #include <stdlib.h> void *calloc(size_t nmemb, size_t size); void *malloc(size_t size); void free(void *ptr); void *realloc(void *ptr, size_t size); Programming Applications of Pointers/Features/ Cons : Pointer is a low level construct in programming which is used to perform high level task. 1.Easy access ,save memory space and time 2.To return more than one value from a function. 3. To pass as arguments/parameters to functions 4. A pointer is an easy way of referencing a data structure. 5. pointers are generally useful in the context where we need a continuous memory allocation. Using pointers dynamic allocation of memory is achieved 6.Passing Parameter by reference 7.Accessing array element 8. Passing string to functions 9. Provides effective way of implementing different data structures as tree, graph, linked list. 10. pointers basically hold the address of a variable. they are mainly used as function parameters to pass values of parameters as references rather than values
Advantages:
- Pointers allow you to implement sharing without copying - Pointers allow modifications by a function that is not the creator of the memory i.e. function A can allocate the memory and function C can modify it, without using globals, which is a no-no for safe programming. - Pointers allow us to use dynamic memory allocation.
Data Pointers
Stacks and Queues Parameter passing to functions (pass by reference) Complex return values from functions Dynamic memory allocation More elegant and flexible method of working with arrays and strings Linked lists "Windowing" streaming data
Function Pointers
Callback functions Pass a function to a function
Common Pointer Pitfalls/Drawbacks/Bottlenecks/Cons: Not assigning a pointer to memory address before using it Illegal indirection
Strings :
(Introduction / Basics/ Concepts) Definition: Strings in C are represented by arrays of characters. The end of the string is marked with a special character, the null character, which is simply the character with the value 0. (The null character has no relation except in name to the null pointer. In the ASCII character set, the null character is named NULL.) The null or string-terminating character is represented by another character escape sequence\0. For example, we can declare and define an array of characters, and initialize it with a string constant: char string[] = "Hello, world!"; C also permits us to initialize a character array without specifying the number of elements. char string[]={G,O,O,D,\0}; Strings In C /C Strings: A string is a sequence/array of characters. C has no native string type; instead we use arrays of char. A special character, called a null, is important because it is the only way the functions that work with a string can know where the string ends. This may be written as \0 (zero not capital o). This is the only character whose ASCII value is zero. Depending on how arrays of characters are built, we may need to add the null by hand, or the compiler may add it for us. The following operations performed on character strings, Reading and Writing strings. Combining Strings together. Copying one string to another. Comparing strings for equality.
Initializing String Variables Character arrays may be initialized when they are declared. C permits a character array to be initialized in one of the following forms, Initializing locations character by character. Partial array initialization. Initializing without specifying the size. Array initialization with a string constant.
If you know all the characters at compile time, you can specify all your data within brackets: Example, char s[6]={h,e,l,l,o};
The compiler allocates 6 memory locations ranging from 0 to 5 and these locations are initialized with the characters in the order specified. The remaining locations are automatically initialized to null characters as shown in the below figure
Note: It is the programmer responsibility to allocate sufficient memory so as to accommodate NULL character at the end. Note that The ASCII values of characters are stored in the memory. Partial Array Initialization If the number of characters values to be initialized is less than the size of the array, then the characters are initialized in the order from 0 th location. The remaining locations will be initialized to NULL automatically. Consider the following initialization,
char s[10]={h,e,l,l,o};
The above statement allocates 10 bytes for the variable s ranging from 0 to 9 and initializes first 5 locations with the characters. The remaining locations are automatically filled with NULL as shown in below figure .
Initialization Without Size If we omit the size of the array, but specify an initial set of characters, the compiler will automatically determine the size of the array. This way is referred as initialization without size.
char s[]={h,e,l,l,o};
In this declaration, even though we have not specified exact number of characters to be used in array s, the array size will be set of the total number of initial characters specified and appends the NULL character.. Here, the compiler creates an array of 6 characters. The array s is initialized as shown in Figure.
Here the length of the string is 5 bytes, but size is 6 bytes. The compiler reserves 5+1 memory locations and these locations are initialized with the characters in the order specified. The string is terminated by Null as shown in the figure
Here are some illegal statements representing initialization of strings, The following declaration creates character array only not a string char s[5]={h,e,l,l,o}; //no location for appending NULL The following declaration is illegal. char str[3]=Good; //size is less than the total characters We cannot separate the initialization from declaration. char str3[5]; str3=Good; Is not allowed.
Similarly, char s1[4]=abc; char s2[4]; s2=s1; /* Error */ Note: Observe the difference between the following ,
0 --> it is an integer zero. Occupies two bytes of memory. 0 --> it is a character constant .It occupies one byte. 0 --> it is a string constant. It occupies two bytes. The first byte contains the value 0 and second byte contains \0. \0 --> it is Null character and occupies 1 byte. \0 --> it is a string containing a null-character. It occupies 2 bytes. Together, the string \0 occupies two bytes.
The string can be read using the scanf function also. The format specifier associated with the string is %s. Syntax for reading string using scanf function is scanf (%s, string_name); Disadvantages The termination of reading of data through scanf function occurs, after finding first white space through keyboard. White space may be new line (\n), blank character, tab(\t). For example if the input string through keyword is hello world then only hello is stored in the specified string. Formatted Output function-printf () The various options associated with printf (): 1. Field width specification 2. Precision specifier 3. Left Justification
W is the field with specified width. S indicates that the string is being used. NOTE: 1. If the string to be printed is larger than the field width w, the entire string will be printed. 2. If the string to be printed is smaller than the field width w, then appropriate numbers of blank spaces are padded at the beginning of the string so as to ensure that field width w is reached.
W is the field specified width N indicates that first n characters have to be displayed. This gives precision. S indicates that the string is being used.
NOTE: The string is printed right justification by default. If w > n, w columns are used to print first n characters .example 2nd and 3rd printf statements. If w < n, minimum n columns are used to print first n characters. Example, 1st and 4th printf statements. 3. Left justification Syntax: %-w.ns
- just before w indicates that string is printed using left justification. W is the field with specified width. S indicates that the string is being printed.
The function accepts string from the keyboard. The string entered includes the white spaces. The input will terminate only after pressing <Enter Key>. Once the <Enter key > is pressed ,a null character(\0) appended at the end of the string.
Advantage
It is capable of reading multiple words from the keyword.
strcmp () function: The strcmp function compares two strings identified by the arguments and has the value 0 if they are equal. If they are not, it has the numeric difference between the first non matching characters in the strings. It takes the following form: strcmp(str1,str2); return value less than 0 means ''str1'' is less than ''str2' return value 0 means ''str1'' is equal to ''str2' return value greater than 0 means ''str1'' is greater than ''str2''
String1 and string2 may be string variables or string constants. Example: strcmp(name1,name2); strcmp(name1,John); strcmp(their ,there);
strcpy () function: it takes the following form: strcpy(string1,string2); and assign the contents of string2 to string1. String2 may be a character array variable or a string constant. Example: strcpy(city ,Delhi); strcpy(city1,city2);
strlen () function: This function counts and returns the number of characters in a string. It takes the form n=strlen(string); Where n is an integer variable, which receives the value of the length counting ends at the first null character.
Example: #include<stdio.h> #include<string.h> void main() { char name[100]="Gore"; printf ("%d", strlen (name)); getch(); } Output: 4 Note, however, that the size of the array is 100
strrev () function Reverses the contents of the string. It takes of the form strrev(string);
Example:
#include<stdio.h>
#include<string.h> void main() { char s[]=hello; strrev(s); puts(s); getch(); } OUTPUT: olleh
strstr () function:
It is a two-parameter function that can be used to locate a sub-string in a string. It takes the form: strstr (s1, s2); Example: strstr (s1,ABC);
The function strstr searches the string s1 to see whether the string s2 is contained in s1.If yes, the function returns the position of the first occurrence of the sub-string. Otherwise, it returns a NULL pointer. Example: if (strstr (s1, s2) ==NULL) printf (substring not found); else printf (s2 is a substring of s1); We also have the functions to determine the existence of a character in a string. Example: strchr (s1,m);
Will locate the last occurrence of the character m. Functions included in <string.h> Operation Function Description
memcpy
Copying
Copies a block of memory Move block of memory Copy string Copy n number characters from string
memmove
strcpy
strncpy
Concatenation
strcat
strncat
memcmp
Comparison strcmp
Compare two blocks of memory Compare two strings Compare two strings using locale Compare first n characters of two strings Transform string using locale
Locate character in block of memory Locate first occurrence of character in string Get span until character in string Locate character in string Locate last occurrence of character in string Get span of character set in string Locate substring Split string into tokens
Other
strrev
memset
strerror
strlen
Character Pointer:
Suppose we wish to store Hello. We may either store it in a string or we may ask the C compiler to store it at some location in memory and assign the address of the string in a char pointer. Consider the following declaration with string initialization, char *p=hello;
Here the string length is 5 bytes. So the compiler allocates 6 bytes memory locations. Probably the characters are stored in the constant memory area of the computer, and the pointer p points to the base address as shown in the below figure
We cannot assign a string to another. But, we can assign a char pointer to another char pointer. Example: char *p1=hello; char *p2; p1=p2; //valid printf (%s, p1); //will print hello *p will refer to a particular character only, p will refer whole string.
Reading strings:
The familiar input function scanf can be used with %s format to read in a string of characters. char address[15]; scanf(%s,address);
Basic Library functions for strings: Function strcpy(s1, s2) strncpy(s1, s2, n) Description Copies the value of s2 into s1 Copies n characters of s2 into s1. Does not add a null. strcat(s1, s2) string.h Appends s2 to the end of s1 strncat(s1, s2, n) string.h Appends n characters of s2 onto the end of s1 strcmp(s1, s2) string.h Compared s1 and s2 alphabetically; returns a negative value if s1 should be first, a zero if they are equal, or a positive value if s2 sbould be first strncmp(s1, s2) string.h Compares the first n characters of s1 and s2 in the same manner as strcmp strlen(s1) string.h Returns the number of characters in s1 not counting the null Since C never lets us assign entire arrays, we use the strcpy function to copy one string to another: #include <string.h> char string1[] = "Hello, world!"; char string2[20]; strcpy(string2, string1); The above code copies the contents of string1 to string2. The standard library's strcmp function compares two strings, and returns 0 if they are identical, or a negative number if the first string is alphabetically ``less than'' the second string, or a positive number if the first string is ``greater.'' Here is an example: char string3[] = "this is"; char string4[] = "a test"; if(strcmp(string3, string4) == 0) printf("strings are equal\n"); else printf("strings are different\n"); This code fragment will print ``strings are different''. Another standard library function is strcat, which concatenates strings. It does not concatenate two strings together and give you a third, new string; what it really does is append one string onto the end of another. Here's an example: char string5[20] = "Hello, "; char string6[] = "world!"; printf("%s\n", string5); strcat(string5, string6); printf("%s\n", string5); Library string.h string.h
The first call to printf prints ``Hello, '', and the second one prints ``Hello, world!'', indicating that the contents of string6 have been tacked on to the end of string5. Notice that we declared string5 with extra space, to make room for the appended characters. The length of the string can be found by using the function strlen() function. char string7[] = "abc"; int len = strlen(string7); printf("%d\n", len);
Arrays of Strings:
A string is an array of characters; so, an array of strings is an array of arrays of characters. Of course, the maximum size is the same for all the strings stored in a two dimensional array. We can declare a two dimensional character array of MAX strings of size SIZE as follows: char names[MAX][SIZE]; Since names is an array of character arrays, names[i] is the character array, i.e. it points to the character array or string, and may be used as a string of maximum size SIZE - 1. As usual with strings, a NULL character must terminate each character string in the array. We can think of an array of strings as a table of strings, where each row of the table is a string as seen in Figure
Figure : Array of Strings We will need an array of strings in our next task to read strings, store them in an array, and print them. NAMES: Read and store a set of strings. Print the strings. We can store a string into names[i] by reading a string using or by copying one into it using strcpy(). Since our task is to read strings, we will use gets(). The algorithm is simple: while array not exhausted and not end of file, read a string into an array element print out the strings in the array of strings We will organize the program in several source files since we will be using some of the functions in several example programs. The program driver and the header file are shown in Figure
The program reads character strings into an array, in this case, names. The program can, of course, serve to read in any strings. The for loop in main() reads strings into an array using gets() to read a string into names[n], the row of the array. That is, the string is stored where names[n] points to. The variable nkeeps track of the number of names read. The loop is terminated either if the number of names equals MAX, or when gets() returns NULL indicating end of file has been reached. Next, the program calls on printstrtab() to print the names stored in the two dimensional array, names. The arguments passed are the array of strings and the number of strings, n. The function, printstrtab() is included in the file strtab.c and its prototype is included in the file strtab.h. Remember, the second range of the two dimensional array of strings must be specified in the formal parameter definition, otherwise the number of columns in a row are unknown and the function cannot access successive rows correctly. A sample interaction for the compiled and linked program is shown below: Sample Session: ***Table of Strings - Names*** Enter one name per line, EOF to terminate vivek ananda shankar G reddy venkatesh varun kumar '136D Names are: vivek ananda shankar G reddy venkatesh varun kumar
# include <stdio.h> int main () { char *name [] = { "Illegal month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; }
Note: When we are using an array of pointers to strings we can initialize the string at the place where we are declaring the array, but we cannot receive the string from keyword using scanf ().
String/Data conversion:
The following functions convert between data types. atof() atoi() itoa() converts an ascii character array to a float converts an ascii character array to an integer converts an integer to a character array
String to data conversion: a to i The string scan function is called sscanf. This function scans a string as though the data were coming from a file. Syntax: int sscanf(char *str,const char *frmt_str,); The first parameter specifies the string holding the data to be scanned. The . Indicates that a variable number of pointers identify the fields into which the formatted data are to be placed. Example: /* convert a string to an integer */ #include <stdio.h> #include <stdlib.h> char string[] = "1234"; main() { int sum; sum = atoi( string ); printf("Sum = %d\n", sum ); } Data to String conversion: i to a The string print function,sprintf, follows the rules of fprintf. Rather than sending the data to a file, it simply writes them to a string. Syntax: int sprintf(char *out_string,const char *format_string,.); The first parameter is a pointer to a string that will contain the formatted output. The format string is the same as printf and follows all of the same rules. The contains the fields that correspond to the format codes in the format string. Example: /* convert an integer to a string */ #include <stdio.h> #include <stdlib.h> main() { int sum; char buff[20]; printf("Enter in an integer ");
scanf(" %d", &sum ); printf( "As a string it is %s\n", itoa( sum, buff, 10 ) ); } Note that itoa() takes three parameters, the integer to b converted a character buffer into which the resultant string is stored a radix value (10=decimal,16=hexadecimal) In addition, itoa() returns a pointer to the resultant string. String to double conversion: a to f atof() converts 'string' to a double-precision floating-point value. 'string' is a sequence of characters that can be interpreted as a numerical value; it has the following format:
[whitespace][sign][digits][.digits][{d|D|e|E}[sign]digits] where:
whitespace any number of tab and space characters are ignored sign + or digits one or more decimal digits d|D|e|E exponent prefixes Usage of atof(): double atof ( const char * str );
This function of stdlib will convert a string to a double.
Example of atof():
#include<stdio.h> #include<stdlib.h> int main () { double a,b; char buffer [256]; printf ( "Input: " ); gets (buffer); a = atof (buffer); b = a/2; printf ( "a= %f and b= %f\n" , a, b ); return 0; }
Wisdom Protects one from destruction. Wisdom is an inner fortification that even ones enemies cannot destroy . Vivekananda GN.....All the Best.....