Memory management, File IO, ...

Memory Layout - Heap

  • Global variables, static variables and program instructions get their memory in permanent storage area
  • local variables are stored in Stack.
  • The memory space between these two region is known as Heap area.
  • This region is used for dynamic memory allocation during execution of the program.
  • The size of heap keep changing.

Memory Allocation

  • The header <stdlib.h> declares functions for storage allocation
  • malloc returns a pointer to space for an object of a specified size, or NULL if the request cannot be satisfied. The allocated space is uninitialized
void *malloc(size_t size)
  • free deallocates the space that previously allocated by calloc, malloc, or realloc
void free(void *P)
  • size_t is an unsigned integer defined in stddef.h as (on my computer):
typedef long unsigned int size_t;

calloc

  • calloc returns a pointer to space for an array of objects, each of size size, or NULL if the request cannot be satisfied. The space is initialized to zero bytes
void *calloc(size_t nobj, size_t size)
  • realloc changes the size of the previously allocated memory by a new size.
  • realloc returns a pointer to the new space, or NULL if the request cannot be satisfied, in which case the old allocated memory is unchanged.
void *realloc(void *p, size_t size)

Example

#include <stdio .h> 
#include <stdlib .h> 
#include <string .h>
int main() {
	char ∗language ;
	language = calloc ( 200, sizeof (char) );
	if( language == NULL ) { 
    fprintf(stderr ,
            "Error − ...\n");
}
else {
	strcpy( language , "C programming language");
}
	printf ("Language : %s\n" , language ); 
  free ( language );
	return 0;
 }

realloc

int main() {
	char ∗language ;
	language = malloc( 25 ∗ sizeof(char) ); 
  if( language == NULL ) {
    fprintf(stderr , "...\n");
}
	else {
	strcpy( language , "C programming language");
}
language = realloc( language , 10 ∗ sizeof(char) ); 
  if( language == NULL ) {
    fprintf(stderr , "...\n");
	}
	else {
	strcat( language , " tutorial");
}
	printf ("Language : %s\n" , language ); 
  free ( language );
	return 0;
 }

Pointer

int main() {
	int ∗iptr = malloc (sizeof(int));
	float ∗fptr = malloc (sizeof(float )); 
  double ∗dptr = malloc ( sizeof (double ));
	∗iptr = 100; 
	∗fptr = 4.13f; 
	∗dptr = 459000.0;
	printf("∗iptr: %d\n", ∗iptr); 
	printf("∗fptr: %.2f\n", ∗fptr); 
	printf("∗dptr: %.2f\n", ∗dptr);
	free(iptr); 
	free(fptr); 
	free(dptr); 
	return 0;
}

File IO

  • fopen opens the named file, and returns a stream, or NULL if the attempt fails
  • FILE *fopen(const char *filename, const char *mode)

Legal values for mode include:

"r" open text file for reading
"w" create text file for writing; discard previous contents if any
"a" append; open or create text file for writing at end of file
"r+" open text file for update (i.e., reading and writing)
"w+" create text file for update; discard previous contents if any
"a+" append; open or create text file for update, writing at end
  • fflush causes any buffered but unwritten data to be written on an output stream
int fflush(FILE *Stream)
  • on an input stream, the effect is undefined
  • It returns EOF for a write error, and zero otherwise
  • fflush(NULL) flushes all output streams
  • fclose flushes any unwritten data for stream, discards any unread buffered input
int fclose(FILE *Stream)
  • frees any automatically allocated buffer, then closes the stream
  • It returns EOF if any errors occurred, and zero otherwise

Writing a file

  • fputc() writes the character value to an output stream
int fputc( int c, FILE *fp );
  • fputs() writes a string to an output stream
int fputs( const char *s, FILE *fp );
  • fprintf write a string to an output stream
int fprintf(FILE *fp, const char *format, ...)

Reading a file

  • fgetc() reads a character from the input file. he return value is the character read, or in case of any error, it returns EOF
  • fgets() reads up to n-1 characters from an input stream. It copies the read string into a buffer, appending a null character to terminate the string.
  • fscanf reads strings from a file, but it stops reading after encountering the first space character

Miscellaneous

Command-line Arguments

  • In C it is possible to accept command line arguments
  • Command-line arguments are given after the name of a program
  • passed to the program by the operating system
  • The full declaration of main looks like this:
int main ( int argc, char *argv[] )
#argc:number of command line arguments including the name of the program
#argv:list of all command line arguments
  #argv[0]: the program name (or an empty string)
  #argv[1] to argv[argc-1]: the actual command line arguments

Variable Arguments

  • Sometimes, you would like to have a function that accept an arbitrary number of arguments
  • for example a function that accepts any number of values and returns the average
  • the last argument is written as ellipses, i.e. three dotes (...)
  • the one just before the ellipses is always an int which will represent the total number variable arguments passed

Header file

  • The header file stdarg.h provides the functions and macros to implement the functionality of variable arguments as follows
  • Define a function with its last parameter as ellipses and the one just before the ellipses is always an int which will represent the number of arguments.
  • Create a va_list type variable in the function definition
  • Use int parameter and va_start macro to initialize the va_list variable to an argument list
  • Use va_arg macro and va_list variable to access each item in argument list
  • Use a macro va_end to clean up the memory assigned to va_list variable

Example

#include <stdio .h> 
#include <stdarg .h>
double average(int num,...) { 
  va_list valist ;
	double sum = 0.0;
	inti;
	va_start(valist , num);
	for (i = 0; i < num; i++) {
    sum += va_arg( valist , int );
  }
	 va_end( valist );
	return sum/num;
}
int main() {
  printf("Average of 2, 3, 4, 5 =%f\n", average (4 , 2 ,3 ,4 ,5));
	printf("Average of 5, 10, 15 =%f\n", average (3 , 5 ,10 ,15));
}

typedef

  • The typedef keyword allows the programmer to create new names for types such as int
  • Typedefs can be used both to provide more clarity to your code and to make it easier to make changes to the underlying data types
  • in C, struct variables must be declared by a combination of the keyword struct and the name of the struct

typedef vs #define

  • #define is a C-directive which is also used to define the aliases for various data types similar to typedef but with the following differences:
  • typedef is limited to giving symbolic names to types only where as #define can be used to define alias for values as well
  • typedef interpretation is performed by the compiler whereas #define statements are processed by the pre-processor

Preprocessors

  • Preprocessors are a way of making text processing with your C program before they are actually compiled
  • Before the actual compilation of every C program it is passed through a Preprocessor.
  • The Preprocessor looks through the program trying to find out specific instructions called Preprocessor directives that it can understand.
  • All Preprocessor directives begin with the # (hash) symbol
#define Substitutes a preprocessor macro. 
#include Inserts a particular header from another file. 
#undef Undefines a preprocessor macro.
#ifdef Returns true if this macro is defined. 
#ifndef Returns true if this macro is not defined. 
#if Tests if a compile time condition is true. 
#else The alternative for #if.
#elif #else and #if in one statement.
#endif Ends preprocessor conditional.
#error Prints error message on stderr.
#pragma Issues special commands to the compiler,using a standardized method.