0% found this document useful (0 votes)
2 views

Chapter 1 Pointers and DMA

The document outlines various applications of the C programming language, including application programming, network programming, system programming, embedded system programming, and device driver programming. It also explains the differences between programs and processes, the compilation and build process, and the use of pointers in C, including pointer manipulation, pointer types, and accessing structures and unions. Additionally, it covers pointer arithmetic, null and void pointers, and the relationship between pointers and arrays.

Uploaded by

tempoabhi1234
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Chapter 1 Pointers and DMA

The document outlines various applications of the C programming language, including application programming, network programming, system programming, embedded system programming, and device driver programming. It also explains the differences between programs and processes, the compilation and build process, and the use of pointers in C, including pointer manipulation, pointer types, and accessing structures and unions. Additionally, it covers pointer arithmetic, null and void pointers, and the relationship between pointers and arrays.

Uploaded by

tempoabhi1234
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

Applications of C

 Application Programming
 GUI, Data Base, Editors, Gaming
 Network programming
 Client-Server, Routing,
 System Programming
 OS, Compliers, Simulators,
 Embedded System Programming
 Cars, Missiles, Robots
 Device Driver Programming
 External hard Disk, Printers
Program v/s Process

 Set of instructions  Set of instructions


 Resides in Hard disk  Resides in Memory
 Passive entity  Active entity
 Does not consume system  Consumes various
resources resources during its life
(except hard disk space) time
Compilation and Build Process
 https://www.youtube.com/watch?v=VDslRumKvRA
hello.c
$gcc hello.c

Pre-Processor # gpp hello.c > hello.i

hello.i

C Compiler # gcc -S hello.i

hello.s

Assembler # as hello.s -o hello.o

hello.o

Linker # gcc hello.o

a.out
Applications of Pointers

 One function allows another function to access it local variables


Eg. Swap Program
 Pointers are the efficient way of transferring data from one function to
another
Eg. Passing arrays to functions
 Command line arguments
Eg. gcc command
 Function pointers
Eg. Accessing functions with address
 Dynamic memory allocation
Eg. Efficient usage of memory
Pointers

 Pointers
 Definitions
 Address space of a process in UNIX
 Invalid pointers and segmentation faults
 Segmentation faults Vs page faults
 Pointers to basic types, Pointer to structures, Pointer to unions
 Pointer initialization, significance of NULL pointer
 Pointers into single dimensional integer and character arrays.
 Pointer Arithmetic, addition and subtractions as defined in ISO C99
A pointer is a variable whose value is the address of another
variable that must be declared before using it to store the address of
any variable.

The general form of a pointer variable declaration is −

data type *var-name;

- type is the pointer's base type

- var-name is the name of the pointer variable

- * used to designate a variable as a pointer.


Take a look at some of the valid pointer declarations −

int *ip; /* pointer to an integer */


double *dp; /* pointer to a double */
float *fp; /* pointer to a float */
char *ch /* pointer to a character */

Size of a pointer variable depends on ? Compiler


The following example makes use of these operations −
#include <stdio.h>
int main ()
{
int var = 20; /* actual variable declaration */
int *ip; /* pointer variable declaration */
ip = &var; /* store address of var in pointer variable*/
printf("Address of var variable: %x\n", &var ); /* address stored in pointer variable */
printf("Address stored in ip variable: %x\n", ip ); /* access the value using the pointer */
printf("Value of *ip variable: %d\n", *ip );
return 0;
}
When the above code is compiled and executed, it produces the following result −
Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20
Pointer manipulation

ptr++; // Pointer moves to the next int position (as if it was an array)
++ptr; // Pointer moves to the next int position (as if it was an array)
++*ptr; // The value of ptr is incremented
++(*ptr); // The value of ptr is incremented
*ptr++; // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value of ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr; // Pointer moves to the next int position, and then get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault
we perform any arithmetic function like increment on a pointer, changes occur as
per the size of their primitive data type.

Size of datatypes on 16-bit Machine : 32-bit Machine

Type Size(bytes) Size(bytes)


int or signed int 2 4
char 1 2
long 4 8
float 4 8
double 8 16
long double 10 32
Incrementing a Pointer
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr; /* let us have array address in pointer */
ptr = var;
for ( i = 0; i < MAX; i++)
{
printf("Address of var[%d] = %x\n", i, ptr );
printf("Value of var[%d] = %d\n", i, *ptr ); /* move to the next location */
ptr++;
}
return 0;
}
When the above code is compiled and executed, it produces the following result −
Address of var[0] = bf882b30
Value of var[0] = 10
Address of var[1] = bf882b34
Value of var[1] = 100
Address of var[2] = bf882b38
Value of var[2] = 200
Decrementing a Pointer
The same considerations apply to decrementing a pointer, which decreases its value by the
number of bytes of its data type as shown below −
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr; /* let us have array address in pointer */
ptr = &var[MAX-1];
for ( i = MAX; i > 0; i--)
{
printf("Address of var[%d] = %x\n", i-1, ptr );
printf("Value of var[%d] = %d\n", i-1, *ptr ); /* move to the previous location */
ptr--;
}
return 0;
}
When the above code is compiled and executed, it produces the following result −
Address of var[2] = bfedbcd8
Value of var[2] = 200
Address of var[1] = bfedbcd4
Value of var[1] = 100
Address of var[0] = bfedbcd0
Value of var[0] = 10
Pointer to Constant Vs Constant Pointer
A constant pointer is a pointer that cannot change the address it Eg: int x=10, y=5;
Int *const ptr= &x;
is holding. In other words, once a constant pointer points to a
variable then it cannot point to any other variable. Mem Loc Value
2000- 10

ptr= &y; is invalid


Eg. int * const ptr; *ptr++; is valid

A pointer to constant is a pointer through which one cannot


Eg: int x=10;
change the value of variable it points. These type of pointers can const int *ptr= &x,
change the address they point to but cannot change the value ptr1;
kept at those address.
*ptr++; is invalid

Ptr1=&x; is valid
Eg. const int* ptr
Pointer to Constant Vs constant pointer
#include<stdio.h>
#include<stdio.h> #include<stdio.h>
int main(void)
int main(void) int main(void)
{ {
{ int var1 = 0,var2 = 0;
int var1 = 0; const int* const ptr = &var1;
int var1 = 0, var2 = 0;
int *const ptr = &var1; const int* ptr = &var1; *ptr = 1;
ptr = &var2; *ptr = 1; ptr = &var2;
printf("%d\n", *ptr); printf("%d\n", *ptr); printf("%d\n", *ptr);
return 0; return 0; return 0;
} } }

A constant pointer to constant is a pointer that can neither change the address its
pointing to and nor it can change the value kept at that address.

Eg. const int* const ptr;


Null pointer Vs void pointer
Null pointer is a special reserved value of a pointer. When a pointer
has that null value it is not pointing anywhere.

Void pointer is a specific pointer type - void * - a pointer that points


to some data location in storage, which doesn't have any specific
type.

So, null pointer is a value, while void pointer is a type.

A pointer which has not been initialized to anything (not even NULL)
is known as wild pointer.

A pointer pointing to a memory location that has been deleted (or


freed) is called dangling pointer.
Invalid Pointer

An invalid pointer reference occurs when a pointer's value


is referenced even though the pointer doesn't point to a
valid block.

One way to create this error is to say p=q;, when q is


uninitialized. The pointer p will then become uninitialized
as well, and any reference to *p is an invalid pointer
reference.

The only way to avoid this bug is to draw pictures of each


step of the program and make sure that all pointers point
somewhere.
Significance of NULL pointer
- A pointer that is assigned NULL (a constant assigned with zero) is called a null pointer.
- It is always a good practice to assign a NULL value to a pointer variable
- This is done at the time of variable declaration.

Consider the following program −


#include <stdio.h>
int main ()
{
int *ptr = NULL;
printf("The value of ptr is : %x\n", ptr );
return 0;
}
When the above code is compiled and executed, it produces the following result −

The value of ptr is 0

In most of the operating systems, programs are not permitted to access memory at address 0 because that
memory is reserved by the operating system. However, the memory address 0 has special significance; it
signals that the pointer is not intended to point to an accessible memory location. But by convention, if a
pointer contains the null (zero) value, it is assumed to point to nothing.
Pointer to Structure

struct Book
{
char name[10];
int price;
};
int main()
{
struct Book a; //Single structure variable
struct Book* ptr; //Pointer of Structure type
ptr = &a;
struct Book b[10]; //Array of structure variables
struct Book* p; //Pointer of Structure type
p = &b;
}
Accessing Structure Members with Pointer
To access members of structure with structure variable, we used the dot . operator. But when we have
a pointer of structure type, we use arrow -> to access structure members.

#include <stdio.h> struct my_structure variable =


int main() {"StudyTonight",35,1};

{ struct my_structure *ptr;

struct my_structure ptr = &variable;

{ printf("NAME: %s\n",ptr->name);

char name[20]; printf("NUMBER: %d\n",ptr->number);

int number; printf("RANK: %d",ptr->rank);

int rank; return 0;

}; }
Union
A union is a special data type available in C that allows to store
different data types in the same memory location.

You can define a union with many members, but only one member
can contain a value at any given time.

Unions provide an efficient way of using the same memory location


for multiple-purpose.

Defining a Union

To define a union, you must use the union statement in the same
way as you did while defining a structure. The union statement
defines a new data type with more than one member for the
program.
The format of the union statement is as follows −
union [union tag]
{
member definition;
member definition; ... member definition;
} [one or more union variables];

union Data
{
int i;
float f;
char str[20];
} data;
Example:

#include <stdio.h>
#include <string.h>
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
printf( "Memory size occupied by data :%d\n“, sizeof(data));
return 0;
}
Accessing Union Members

To access any member of a union, we use the member


access operator (.).

The member access operator is coded as a period between


the union variable name and the union member that we
wish to access.

You would use the keyword union to define variables of


union type.
#include <stdio.h> printf( "data.i : %d\n", data.i);
#include <string.h> printf( "data.f : %f\n", data.f);
union Data printf( "data.str : %s\n", data.str);
{ return 0;
int i; }
float f; .

char str[20];
};
int main( )
Note : the output will be the last inserted
{ value, others junk value
union Data data;
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
#include <stdio.h> printf( "data.str : %s\n", data.str);
#include <string.h> return 0;
union Data }
{
int i;
float f;
char str[20];
};
Note : one member is being used at a
int main( ) time.
{
union Data data;
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
Pointer and Arrays
When an array is declared, compiler allocates sufficient amount of memory to contain all the
elements of the array. Base address i.e address of the first element of the array is also allocated
by the compiler.

Suppose we declare an array arr,

int arr[5] = { 1, 2, 3, 4, 5 };

Assuming that the base address of arr is 1000 and each integer requires two bytes, the five
elements will be stored as follows

Here variable arr will give the base address, which is a constant pointer pointing to the
element, arr[0]. Therefore arr is containing the address of arr[0] i.e 1000.
In short, arr has two purpose- it is the name of an array and it acts as a
pointer pointing towards the first element in the array.

arr is equal to &arr[0] // by default

We can declare a pointer of type int to point to the array arr.

int *p;
p = arr;
or p = &arr[0]; //both the statements are equivalent.

Now we can access every element of array arr using p++ to move from
one element to another.

NOTE : one cannot decrement a pointer once incremented. p-- won't


work.
Pointer to Array

As studied above, we can use a pointer to point to an Array, and then


we can use that pointer to access the array. Lets have an example,
int i;
int a[5] = {1, 2, 3, 4, 5};
int *p = a; // same as int*p = &a[0]
for (i=0; i<5; i++)
{
printf("%d", *p);
p++;
}
In the above program, the pointer *p will print all the values stored
in the array one by one. We can also use the Base address (a in
above case) to act as pointer and print all the values.
The generalized form for using pointer with an array,
*(a+i)
is same as
a[i]
Pointer to Multidimensional Array

A multidimensional array is of form, a[i][j]. Lets see how we can make a


pointer point to such an array.

As we know now, name of the array gives its base address.

In a[i][j], a will give the base address of this array, even a+0+0 will also
give the base address, that is the address of a[0][0] element.

Here is the generalized form for using pointer with multidimensional


arrays.

*(*(a + i) + j) is same as a[i][j]


Pointer and Character strings

Pointer can also be used to create strings. Pointer variables of char type are treated
as string. char *str = "Hello";

This creates a string and stores its address in the pointer variable str. The
pointer str now points to the first character of the string "Hello".
Another important thing to note that string created using char pointer can be
assigned a value at runtime.
char *str;
str = "hello"; //this is Legal

The content of the string can be printed using printf() and puts().
printf("%s", str);
puts(str);

Notice that str is pointer to the string, it is also name of the string. Therefore we do
not need to use indirection operator *.
Array of Pointers

We can also have array of pointers. Pointers are very helpful in handling character
array with rows of varying length.

char *name[3]={
"Adam",
"chris",
"Deniel"
};
//Now see same array without using pointer
char name[3][20]= {
"Adam",
"chris",
"Deniel"
};

In the second approach memory wastage is more, hence it is prefered to use pointer
in such cases.
Passing Pointer to a Function
 When we pass a pointer as an argument instead of a variable then the address of
the variable is passed instead of the value.
 So any change made by the function using the pointer is permanently made at the
address of passed variable. This technique is known as call by reference in C.
#include <stdio.h> printf("\nValue of v2 is: %d", v2);
void swapnum(int *num1, int *num2)
{ /*calling swap function*/
int tempnum; swapnum( &v1, &v2 );

tempnum = *num1; printf("\nAfter swapping:");


*num1 = *num2; printf("\nValue of v1 is: %d", v1);
*num2 = tempnum; printf("\nValue of v2 is: %d", v2);
} }

int main( )
{
int v1 = 11, v2 = 77 ;
printf("Before swapping:");
printf("\nValue of v1 is: %d", v1);
Function Returning Pointer
The syntax of a function returning a pointer is as follows.
Syntax: type *function_name(type1, type2, ...);

#include<stdio.h>
int *return_pointer(int *, int); printf("Address of ptr = %u\n\n" , ptr);
// this function returns a pointer of type int printf("Value at %u is %d\n", ptr, *ptr);
// signal to operating system program ran fine
int main() return 0;
{ }
int i, *ptr;
int arr[] = {11, 22, 33, 44, 55}; int *return_pointer(int *p, int n)
i = 4; {
p = p + n;
printf("Address of arr = %u\n", arr); return p;
}
ptr = return_pointer(arr, i);

printf("\nAfter incrementing arr by 4 \n\n");


Pointer to functions/ Function Pointers
 A function pointer can point to a specific function when it is assigned the name of that function.
Eg.: int sum(int, int);
int (*s)(int, int);
s = sum;
Here s is a pointer to a function sum . Now sum can be called using function pointer s along with
providing the required argument values.
int sum (int num1, int num2) //Calling function using function pointer
{
return num1+num2; int op1 = f2p(10, 13);
}
int main() //Calling function in normal way using function name
{
/* The following two lines can also be written in a single int op2 = sum(10, 13);
* statement like this: void (*fun_ptr)(int) = &fun; */
printf("Output1: Call using function pointer: %d",op1);
int (*f2p) (int, int); printf("\nOutput2: Call using function name: %d", op2);
f2p = sum;
return 0;
}
Dynamic Allocation

 When an array program is compiled, the compiler estimates the amount of


memory required for the variables, and also the instructions defined by you
as part of the program.

 The compiler writes this information into the header of the executable file
that it creates. When the executable is loaded into memory at runtime, the
specified amount of memory is set aside.

 A part of the memory allocated to the program is in an area of memory


called a runtime stack or the call stack. Once the size of the stack is fixed,
it cannot be changed dynamically.
Problem with Arrays
 Sometimes
 Amount of data cannot be predicted beforehand
 Number of data items keeps changing during program execution
 Example: Seach for an element in an array of N elements
 One solution: find the maximum possible value of N and allocate an
array of N elements
 Wasteful of memory space, as N may be much smaller in some
executions
 Example: maximum value of N may be 10,000, but a particular run
may need to search only among 100 elements
 Using array of size 10,000 always wastes memory in most cases
Better Solution

 Dynamic memory allocation


 Know how much memory is needed after the program is
run
 Example: ask the user to enter from keyboard
 Dynamically allocate only the amount of memory needed
 C provides functions to dynamically allocate memory
 malloc, calloc, realloc
Memory Allocation Functions
 malloc
 Allocates requested number of bytes and returns a pointer to
the first byte of the allocated space
 calloc
 Allocates space for an array of elements, initializes them to
zero and then returns a pointer to the memory.
 free
 Frees previously allocated space.
 realloc
 Modifies the size of previously allocated space.
Allocating a Block of Memory

 A block of memory can be allocated using the function malloc


 Reserves a block of memory of specified size and returns a
pointer of type void
 The return pointer can be type-casted to any pointer type
 General format:
type *p;
p = (type *) malloc (byte_size);
Example

p = (int *) malloc(100 * sizeof(int));

 A memory space equivalent to 100 times the size of an


int bytes is reserved
 The address of the first byte of the allocated memory is
assigned to the pointer p of type int

400 bytes of space


Points to Note
 malloc always allocates a block of contiguous bytes
 The allocation can fail if sufficient contiguous memory
space is not available
 If it fails, malloc returns NULL

if ((p = (int *) malloc(100 * sizeof(int))) == NULL)


{
printf (“\n Memory cannot be allocated”);
exit();
}
Using the malloc’d Array
 Once the memory is allocated, it can be used with pointers, or with array
notation
 Example:
int *p, n, i;
scanf(“%d”, &n);
p = (int *) malloc (n * sizeof(int));
for (i=0; i<n; ++i)
scanf(“%d”, &p[i]);

The n integers allocated can be accessed as *p, *(p+1), *(p+2),…, *(p+n-1)


or just as p[0], p[1], p[2], …,p[n-1]
Example
printf("Input heights for %d
int main() students \n",N);
{ for (i=0; i<N; i++)
int i,N; scanf ("%f", &height[i]);
float *height;
float sum=0,avg; for(i=0;i<N;i++)
sum += height[i];
printf("Input no. of students\n");
scanf("%d", &N); avg = sum / (float) N;

height = (float *) printf("Average height = %f \n",


malloc(N * sizeof(float)); avg);
free (height);
return 0;
}
Releasing the Allocated Space: free

 An allocated block can be returned to the system for future use


by using the free function
 General syntax:
free (ptr);
where ptr is a pointer to a memory block which has been
previously created using malloc
 Note that no size needs to be mentioned for the allocated block,
the system remembers it for each pointer returned
Using an array of pointers

We can create an array of pointers of size and to dynamically allocate memory for every row.

#include <stdio.h>
for (i = 0; i < r; i++)
#include <stdlib.h>
for (j = 0; j < c; j++)
arr[i][j] = ++count; // Or *(*(arr+i)+j) =
int main()
++count
{
for (i = 0; i < r; i++)
int r = 3, c = 4, i, j, count;
for (j = 0; j < c; j++)
int *arr[r];
printf("%d ", arr[i][j]);
for (i=0; i<r; i++)
/* Code for further processing and free the
arr[i] = (int *)malloc(c * sizeof(int));
dynamically allocated memory */
// Note that arr[i][j] is same as (*(arr+i)+j)
return 0;
count = 0;
}
Using pointer to a pointer

We can create an array of pointers also dynamically using a double pointer.

#include<stdio.h> for (j = 0; j < c; j++)


#include <stdlib.h> arr[i][j] = ++count; // OR *(*(arr+i)+j) = ++count

int main() for (i = 0; i < r; i++)


{ for (j = 0; j < c; j++)
int r = 3, c = 4, i, j, count; printf("%d ", arr[i][j]);

int **arr = (int **)malloc(r * sizeof(int *)); /* Code for further processing and free the
for (i=0; i<r; i++) dynamically allocated memory */
arr[i] = (int *)malloc(c * sizeof(int));
return 0;
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
}
Using double pointer and one malloc call for all rows

#include<stdio.h>
#include<stdlib.h>
for (i = 0; i < r; i++)
int main() for (j = 0; j < c; j++)
{ arr[i][j] = ++count; // OR *(*(arr+i)+j) = ++count
int r=3, c=4;
int **arr;
int count = 0,i,j; for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr = (int **)malloc(sizeof(int *) * r); printf("%d ", arr[i][j]);
arr[0] = (int *)malloc(sizeof(int) * c * r);
return 0;
for(i = 0; i < r; i++)
arr[i] = (*arr + c * i);
}

You might also like