Your browser doesn't support JavaScript c Archives - Windows Programming

C-overview

The C programming language was originally designed for and implemented on the UNIX operating system  in 1972 by Dennis Ritchie at bell laboratories of AT&T.  C evolved from two previous programming languages BCPL and B.  Although, C was widely used to develop the UNIX operating system, nowadays also almost all major operating systems are written in C and C++.  In 1983 a committee was established to create an ANSI (American National Standards Institute) standard that would define the C language and this was finally implemented in 1989.  The resulting standard was typically referred to as ANSI/ISO Standard C.  During the 1990s, a new standard for C was developed and is usually referred to as C99. C89 is however the version of C in widest use enjoying the greater compiler compatibility and producing the most portable code.It also forms the basis for C++

Some free C compilers

Visual studio community edition>
NetBeans IDE>
Eclipse IDE>
Dev C++
Code Blocks

Dynamic Memory Allocation

Allocating memory manually during run-time is known as dynamic memory allocation.  Dynamic memory allocation requires the programmer to know how much memory to allot when the program is written.  All the functions for handling dynamic memory allocation must include the header file stdlib.h.  

The amount of memory available for allocation will depend on the system.  When a memory allocation function is called, the return value must be checked to ensure the memory was allocated successfully. If the memory allocation fails the programs must be able to handle the failure.

There are 4 library functions defined for dynamic memory allocation in C. They are malloc(), calloc(), realloc() and free().

The malloc() Function

 The malloc() function allocates a memory block of the specified number of bytes. It returns a pointer of type void which can be cast into a pointer of any form. The prototype is –

#include <stdio.h>
#include <stdlib.h>
int main () {
 char *str;
/* Initial memory allocation */
 str = (char *) malloc(25);
 strcpy(str, "malloc memory string");
 printf("String = %s, Address = %u\n", str, str);
/* Reallocating memory */
 int *i;
 i = (int *) malloc(1 );
 *i=100;
 printf("Integer = %i, Address = %u\n", *i, i);
 free(str);
 free(i);
 return(0);
}

The calloc() function

calloc() allocates multiple blocks of memory and initialises them to zero.  The prototype is-

void *calloc(size_t nitems,size_t size)

nitems − This is the number of elements to be allocated.
size − This is the size of elements.

#include <stdio.h>
#include <stdlib.h>
int main () {
 int *ptr;
 ptr = (int*)calloc(4, sizeof(int));
 if (ptr != NULL)
puts("Memory allocation was successful.");
else
puts("Memory allocation failed.");
 for(int i=0 ; i < 4 ; i++ ) {
 ptr[i]=i;
 }
 for(int i=0 ; i < 4 ; i++ ) {
 printf("[%i]", ptr[i]);
 }
 free( ptr );
 return(0);
}

The realloc() Function 

If the dynamically allocated memory is insufficient or more than required, you can change the size of the block of memory previously allocated memory using realloc() function.  The prototype is-

ptr = realloc(void ptr,size_t size);

The ptr argument is a pointer to the original block of memory. The new size, in bytes, is specified by size.

The free() function

Dynamically allocated memory created with either calloc() or malloc() has to be manually released. The prototype is-

free(ptr);

The free() function releases the memory pointed to by ptr. This memory must have been allocated with malloc(), calloc(), or realloc().

#include <stdio.h>
#include <stdlib.h>
int main () {
 char *str;
 /* Initial memory allocation */
 str = (char *) malloc(20);
 strcpy(str, "malloc memory string");
 printf("\n String = %s", str );
 /* expand memory */
str = realloc(str, 60);
 strcpy(str, "expand malloc memory string to a total of 50 characters");
 printf("\n String = %s", str);
 str = realloc(str, 14);
 /*shrink memory */
 strcpy(str, "shrink memory ");
printf("\n String = %s", str);
 free(str);
 return(0);
}

Manipulating Memory Blocks

memset –  The memset() function sets all bytes in a block to a specified value. In addition, memset can also be used for copying and moving information from one location to
another.  The function prototype is

void *memset(void *dest, int c, size_t count);

The parameter dest points to the start of a block of memory to be changed, c is the value to set, and count is the number of bytes, starting at dest, to be set. 

memcpy – The memcpy() function copies a specified number of bytes of data between memory blocks. The function prototype is

void *memcpy(void *dest, void *src, size_t count);

The parameters dest and src point to the destination and source memory blocks and count specifies the number of bytes to be copied.  If the two blocks point to the same area of memory the function may fail

memmove – The memmove() function copies a specified number of bytes from one memory block to another however unlike memcpy() it can handle overlapping memory blocks. The prototype is

void *memmove(void *dest, void *src, size_t count);

The parameters dest and src point to the destination and source memory blocks. Count specifies the number of bytes to be copied. 

#include <stdio.h>
#include <string.h>
char messageorg[60] = "This is the original message";
char messagenew[60] = "";
int main( void )
{
printf("\n%s", messageorg);
memset(messageorg, 32, 7);
printf("\n%s", messageorg);
memmove(messagenew ,messageorg+12, 18);
printf("\n%s", messagenew);
return 0;
}

Type Conversion

Type casting refers to the practice of changing variable types. The compiler will automatically change one type of data into another if it makes sense. For instance, if you assign an integer value to a floating-point variable, the compiler will convert the int to a float.

Type conversion in C can be classified into Implicit and explicit type conversions.

Implicit Type Conversion

Implicit or automatic type conversions are performed automatically by the C compiler without any action on the part of the programmer. Data types of the variables are upgraded to the data type of the variable with the largest data type. Implicit conversions can result in loss of information. An example is the loss of the sign when signed is implicitly converted to unsigned or an overflow can occur when long is implicitly converted to float. 

// An example of implicit conversion 
int main()
{
int x = -5; // integer x
float z = x; // x is implicitly converted to float;
char c=x+40;// x is implicitly converted to the char character #;
unsigned int y=x;// x is implicitly converted to unsigned int with loss of data;
printf("z = %f", z);
printf("\n");
printf("c = %c", c);
printf("\n");
printf("y = %u", y);
return 0;
}

Explicit Type Conversion

Explicit type casting is user-defined and uses the cast operator to explicitly specify type conversions.  A variable typecast consists of a type name, in parentheses, before an expression. These casts can be performed on arithmetic expressions and pointers. The resulting expression is converted to the type specified by the cast. One use of an explicit cast is to avoid losing the fractional part of the answer in an integer division. The syntax is:

int main()
{
float a;
int b = 2, c = 3;
a = (float) b / (float) c; // This is type-casting
printf("%f", a);
}

Advanced Pointers

Pointers to Pointers (Multiple Indirection)

A normal pointer contains the address of a variable. When defining a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the location of the variable.  A pointer to a pointer is declared by placing an additional asterisk in front of the variable name. For example, the following declaration declares a pointer to a pointer of type int 

int **var;

Accessing that value pointed to in the above direct is by applying the asterisk operator twice, as is shown below

#include <stdio.h>
int main(void) {
// declare and populate 2d array
int value[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int *ptr = &value[0][0]; // set pointer ptr to array value
int total_cells = 12, i;
// output elements of the array value by using pointer ptr
for (i = 0; i < total_cells; i++) {
printf("%d ", *(ptr + i));
}
return 0;
}

Pointers and Multidimensional Arrays

To create a pointer to a multidimensional array assign the address of the first element of the array to use the pointer address as below

int *ptr = &num[0][0];

The multi-dimensional array num will be saved as a continuous block in memory. To move between each element the value of ptr will need to be incremented by one.

In the following code segments, the num array contents are printed by using a for loop and incrementing the value of ptr.

#include <stdio.h>
int main(void) {
// declare and populate 2d array
int value[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int *ptr = &value[0][0]; // set pointer ptr to array value
int total_cells = 12, i;
// output elements of the array value by using pointer ptr
for (i = 0; i < total_cells; i++) {
printf("%d ", *(ptr + i));
}
return 0;
}

Array of pointers

An array of pointers is an array that holds memory locations. The following statement declares an array of 5 pointers to type char –

char *str[5];

Each element of the str array acts as an individual pointer to type char. These declarations can be combined with initialisation statements as below

char *str[5] = { “one”, “two”, “three” };

This code declares an array of 5 pointers to type char and initialises them to point to 5 strings. It then uses a for loop to display each element.

# include <stdio.h>
int main( void )
{
char *str[5] = { "One", "Two", "Three", "Four","five"};
int count;
for (count = 0; count < 5; count++)
printf("%s ", str[count]);
printf("\n");
return 0;
}

Pointers to Functions

A pointer to a function points to the address of the executable code of the function.  As with all C variables, it is necessary to declare a pointer to a function before using it. The general form of the declaration is as follows:

type (*function_ptr)(parameter_list);

Coded examples of how to declare some function pointers are listed below

int (*function)(int x);
char (*function)(char *p[]);
void (*functions)();

Parentheses are used around the pointer name to override operator precedence. Without the parenthesis, the function declaration will not be evaluated in the correct order.

Function pointers are useful for implementing callback mechanisms and passing the address of a function to another function. They are also useful for storing an array of functions dynamically.

The following short program demonstrates how to declare and call a function pointer

#include <stdio.h>
void function(char arrayvalue[30]);/*function declaration*/
void (*ptrfunc)(char arrayvalue[30]);/* The pointer declaration. */
int main( void )
{
ptrfunc = function;/* Initialise ptrfuch to address of function. */
 char arrayvalue[30]="outside array";
 printf(" %s\n", arrayvalue);
 ptrfunc(arrayvalue);//call function use *ptrfunc
 printf(" %s\n", arrayvalue);
return 0;
}
void function(char arrayvalue[30])
{
 strcpy(arrayvalue, "function return");/*change value of arrayvalue*/
}

Unions

A union is a special data type that stores different data types in the same memory location. Unions are similar to structures in that a union can be defined with many members, but only one member can contain a value at any given time.

Declaring, and Initializing Unions

Unions are defined and declared in the same fashion as structures however the keyword union is used instead of struct. The union is created only as big as necessary to hold its largest data member. A union can be initialised on its declaration but because only one member can be used at a time, only one member can be initialised. Unions initialised with a brace-enclosed initialiser only initialise the first member of the union but individual members can be initialised by using a designated assignment value(see initialising structures).  The format and initialisation of the union statement are as follows:

#include <stdio.h>
int main( void )
{
union shared_tag {
char c;
int i;
float f;
double d;
} shared={33};
printf("%c character value",shared.c);
printf("\n%d integer value ",shared.i);
printf("\n%f float value",shared.f);
printf("\n%d double value",shared.d);
shared.i = 33;
printf("\n%c",shared.c);
printf("\n%i",shared.i);
printf("\n%f",shared.f);
printf("\n%f",shared.d);
shared.d = 33.333333333333;
printf("\n%c",shared.c);
printf("\n%i",shared.i);
printf("\n%f",shared.f);
printf("\n%f",shared.d);
return 0;
}

Individual union members can be accessed by using the member operator however, only one union member should be accessed at a time.

Unions and Pointers

Unions like structures can be accessed and manipulated by pointers and are declared by preceding the variable name with an asterisk. The individual member variables can be accessed by using the → operator

#include <stdio.h>
int main(void) 
{
union data
{
char c[10];
int i;
};
union data charvalue={"union data"};
union data *ptrcharvalue;
ptrcharvalue=&charvalue;
union data intvalue={13};
union data *ptrintvalue;
ptrintvalue=&intvalue;
printf("%s", ptrcharvalue->c);
printf("\n%i",ptrintvalue->i);
return 0;
}

This union can hold either a character value c or an integer value i but only one value at a time.

Structures

A structure is a user-defined collection of one or more variables grouped under a single name. This allows a programmer to wrap related variables with different data types into a single entity. This makes it easier to manipulate data in the program. The variables in a structure can be of different data types. Each variable within a structure is called a member of the structure.

Defining and Declaring Structures

The struct keyword is used to declare the beginning of a structure definition followed immediately by the name of the structure. Following the structure tag is an opening curly brace followed by a list of the structure’s member variables and a closing curly brace. Once the structure type has been defined, variables of that structure type can then be declared with structure definition or after the structure is defined (see below)

struct account
{
int accountno;
char *lastname;
char *firstname;
int age;
unsigned int telephone;
} user1;//structure variable defined with structure
struct account user2, user3;//structure variable outside of the structurevid, Jack;

Note: In C++, the struct keyword is optional before the variable declaration. In C, it is compulsory.

Accessing Members of a Structure

Structure members are accessed using the dot operator operator between the structure name and the member name. Thus, to set the value of variable age for user1 in the above structure account use the following –

user1.age = 21;

Initialise Structures

When initialising a struct, the initialiser consists of a brace-enclosed, comma-separated list of values in the same order as the variables in the structure definition.

For instance to initialise a struct variable user4 using the structure above –

struct account user4={123,"john","doe",12,123456789};

Structure members cannot be initialised within the declaration because when a datatype is declared, no memory is allocated for that datatype. Memory is allocated only when variables are created.

Designated Initialisation – allows structure members to be initialised in any order. Each value is preceded by a designated initialiser corresponding to the structure variable name. Initialisation then moves forward in order of declaration if no further designated initialisers are specified. This feature has been added to the C99 standard. For example –

struct account user5={.lastname="jill","doe",123456789};

Any remaining members not initialised will be set to Zero.

Arrays of Structures

An array of structures is a sequential collection of structures. After the structure has been defined, an array of structures is declared as follows-

struct userdetails list[100];

The above statement declares an array named list that contains 100 elements. Each element is a structure of type userdetails and is identified by subscript. The structure data can be manipulated by specifying the appropriate index value of the array. Like a standard Array, an array of structures can be initialised at compile time.

Structures and Pointers

Structures can be accessed and manipulated by pointers. Pointers to structures can be declared by preceding the variable name with an asterisk. The individual member variables are accessed using the operator instead of the .(dot) operator

#include <stdio.h>
int main(void) 
{
struct account{
unsigned int accountno;
char *firstname;
char *lastname;
unsigned int telephone;
} user1={123,"joe","blogs",123456789};//structure variable user1 defined and initiated
struct account *ptrStr;//create pointer of type struct account
ptrStr = &user1;//set pointer to address of user1

printf("%d %s %s %d", ptrStr->accountno,ptrStr->firstname, ptrStr->lastname,ptrStr->telephone);//access elements using ->
return 0;
}

Passing Structures as Arguments to Functions

An entire structure can be passed to a function as a parameter. This structure can be transferred to a function either using call by value or call by reference scheme

#include <stdio.h>
struct account{ //declare stucture
unsigned int accountno;
char *firstname;
char *lastname;
unsigned int telephone;
};
void function1(struct account user1copy) //declare fuction with argument type struct account
{
 printf("%d\n",user1copy.accountno);
 printf("%s\n",user1copy.firstname);
 printf("%s\n",user1copy.lastname) ;
 printf("%d\n",user1copy.telephone);
}

int main(void) 
{
 struct account user1={123,"joe","blogs",123456789};//initialise structure
function1(user1);//call structure passing parameter user1
return 0;
}

Passing a structure parameter by value – To Pass a structure parameter by value declare the function to use the type of structure you’ve created. When the function is called, a copy of the structure is created and used by the function. Any modification to the structure made inside of the function won’t the effect original.

Passing a structure parameter by reference – To be able to change the structure inside of our function, then it must be passed by reference. Any changes made to the structure members are reflected in the original structure. This is because pointers deal directly with the data stored in the memory.

Structures Within Structures

In C, a structure declaration can be placed inside another structure (nesting). This declaration can either be an Embedded Structure Declaration or by making two separate structure declarations.

#include <stdio.h>
int main(void) {
struct outer {//declare outer stucture
int member1;
int member2;
int member3;

struct embedded{//declare inner structure
int member_1;
int member_2;
int member_3;
} embeddedvar;//declare inner struct variable
} outervar={3,4,5,{1,2,3}};//declare outer stuct variable and initialise outer values and then inner values

// structure embedded
printf("%d", outervar.embeddedvar.member_1);//output embedded member_1
printf("%d", outervar.member1);//output member1
return 0;
}

Separate nested Structure example

#include <stdio.h>
int main(void) {
struct embedded
{
int member_1;
int member_2;
int member_3;
};

struct outer
{
struct embedded embeddedvar; //declare embadded variable
int member1;
int member2;
int member3;
} outervar={{1,2,3},3,4,5};

printf("%d", outervar.embeddedvar.member_1);
printf("%d", outervar.member1);
return 0;
}

Pointers

A pointer is a variable that stores a memory address. A pointer declaration takes the following form:

datatype *pointer_name;

Here, datatype is the pointer’s base type and must be a valid C data type and pointer_name is the user-defined name. The asterisk indicates that the declaration is a pointer. The base type is important because the compiler needs to know how many bytes make up the value pointed to. 

Initialising a Pointer.

Pointer initialisation is the process of assigning the address of a variable to a pointer variable. Each pointer is set to the address of the first byte of the pointed-to variable. When a variable’s address is unknown during the declaration, a null value should be assigned to the pointer. A pointer which is assigned a null value is called a null pointer.  A non-initialised pointer is called a wild pointer and will contain a random or junk value. Wild pointers are dangerous because they cause a program to access invalid memory locations leading to unpredictable results.  To store the address of this variable in a pointer use the referencing operator.

Assigning and Accessing Values

The indirection operator or dereferencing operator (*) operates on a pointer and returns the value stored in the address kept in the pointer variable.

In the example below, pTr is created as an int pointer initialised with a NULL value.  This pointer is then assigned to the address of the int variable a_value . The dereferencing operator is then used to output the value stores at the address of pTr. 

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int a_value = 30; // declares int variable to value 30
int * pTr=NULL;// declares pointer name pTr of type int and assigns NULL value
pTr= &a_value; //sets pointer pTr to address of a_value
printf("%d",*pTr);
}

Pointer Arithmetic

There are only four arithmetic operators that can be used on pointers: ++, – –, +, and –

An increment or decrement operation on a pointer will point to the next value in the memory block. The new location will represent the location of the next variable value and not the next byte of memory. For instance, using the ++ on an int pointer tells the compiler to point to the next consecutive integer. Decrementing pointers ( — ) has the opposite effect. The pointer address is decremented by the size of the type being pointed to. This ensures that the pointer points to the beginning of some valid data and not an arbitrary memory location. In the case of char pointer, an increment or decrement will only change the pointer value by 1 since characters are one byte long. Every other pointer type will increase or decrease by the size of its base type.

Pointer to an Array

Pointers can also be used to address elements of an array. When an array is declared the compiler allocates sufficient memory to access all the elements of that array. The base address is the address of the first element. If a pointer is declared to point to the array then each array element can be accessed by increasing or decreasing this pointer. 

#include <stdio.h>
int main() { 
int a[5]={1,2,3,4,5};//declare array
int *ptr=a;//set pointer *ptr to start of array
for (int i=1;i<=5;i++)
{
 printf ("%d",*ptr);//dereference value held at pointer address
 *ptr++;//increase pointer
}
}

Note that there is no requirement to use the address operator (&) when assigning a pointer to an array

String Manipulation

To address the task of string manipulation, C supports large numbers of string handling functions in the standard library “string.h”. The more useful string-handling functions are discussed below:

strlen

The strlen (str) function takes a single argument, in the form of a character and returns the length of the string. The strlen() function is defined in <string.h> header file. The prototype of strlen is

size_t strlen(const char *str);

The following short program demonstrates the strlen function

#include <stdio.h>
#include <string.h>
int main( void )
{
size_t length;
char buf[100];
puts("\nEnter a line of text, a blank line to exit.");
gets(buf);
length = strlen(buf);
printf("\nThat line is %u characters long.", length);
return 0;
}

strcpy()

The library function strcpy() copies an entire character array to another character array. Its prototype is as follows:

char* strcpy(char* destination, const char* source);

The following short program demonstrates the strcpy function

#include <stdio.h>
#include <string.h>
int main()
{
 char str1[10]= "copy array";
 char str2[10];
 strcpy(str2, str1);
 puts(str2);
 return 0;
}

strncpy()

The library function strncpy() copies a specified number of characters from one character array to another character array.  Its prototype is

char *strncpy(char *destination, const char *source, size_t);

Copies up to n characters from the string pointed in source to the string pointer in destination. In a case where the length of src is less than that of n, the remainder of dest will be padded with null bytes. 

The following short program demonstrates the strncpy function

#include <stdio.h>
#include <string.h>
char dest_string[] = "";
char source_string[] = "copied";
int main( void )
{
size_t n=6;
printf("\nBefore strncpy destination = %s", dest_string);
strncpy(dest_string, source_string, n);
printf("\nAfter strncpy destination = %s\n",source_string);
return 0;
}

strcat()

The function appends a copy of a char array (str2) onto the end of another char array (str2), moving the terminating null character to the end of the new array. There must be enough space in this new array to hold the copied string. The prototype of strcat() is

char *strcat(char *str1, const char *str2);

The following short program demonstrates the strcat function

#include <stdio.h>
#include <string.h>
char source[20] = "source";
char destination[20] = "destination ";
int main( void )
{
printf("This is the source string = %s\n", source);
printf("This is the destination string = %s\n", destination);
strcat(destination,source);
printf("Combined string = %s\n", destination);
return 0;
}

strncat()

The library function strncat() also performs string concatenation but has an additional option to specify how many characters of the source string are appended to the end of the destination string. The prototype is

char *strncat(char *str1, const char *str2, size_t n);

The following short program demonstrates the strncat function

/* The strncat() function. */
#include <stdio.h>
#include <string.h>
char str1[] = "123456789";
int main( void )
{
char str2[27];
strcpy(str2,"");
strncat(str2, str1, 5);
puts(str2);
return 0;
}

strcmp()

The function strcmp() compares two strings, character by character. This function starts by comparing the first character of each string. If they are equal then it continues with the following pairs until the characters differ or until a terminating null-character is reached. The prototype of strcmp() is

int strcmp(const char *str1, const char *str2);

For return values see the table below:

return valueindicates
<0the first character that does not match has a lower value in ptr1 than in ptr2
0the contents of both strings are equal
>0the first character that does not match has a greater value in ptr1 than in ptr2

The following short program demonstrates the strcmp function

#include <stdio.h>
#include <string.h>
char str1[] = "123456789";
char str2[] = "12346789";
int main( void )
{
int i=strcmp(str1,str2);
printf("\n%i ",i);
return 0;
}

strncmp

The library function strncmp() compares a specified number of characters of one char array to another char array. The method of comparison and return values are the same as for strcmp(). The prototype is

int strncmp(const char *str1, const char *str2, size_t n);

The following short program demonstrates the strncmp function

/* The strcmp() function. */
#include <stdio.h>
#include <string.h>
char str1[] = "123456789";
char str2[] = "12346789";
int main( void )
{
int i=strncmp(str1,str2,7);
printf("\n%i ",i);
//puts(i);
return 0;
}

strchr

The strchr() function searches for the first occurrence of a specified character in a string. The prototype is

char *strchr(constchar *str, int ch);

The search direction is from left to right until the character ch is found or the terminating null character is found.  The returns a pointer to the first occurrence of the character c in the string str, or NULL if the character is not found. Since str is a pointer to the first character in the string, the position of the found character in the array can  be calculated by subtracting str from the pointer value returned by strchr()

The following short program demonstrates the strchr function

/* Thestrchr() function. */
#include <stdio.h>
#include <string.h>
char *location;
char str1[] = "123456789";
char ch='7';
int position=0;
int main( void )
{
location=strchr (str1, ch);
position=location-str1;
printf("\n%i ",position);
return 0;
}

strrchr()

The library function strrchr() is identical to strchr() , with the exception that it searches a char array for the last occurrence of a specified character. The prototype is

char *strrchr(const char *str, int ch);

The function strrchr() returns a pointer to the last occurrence of ch in str and NULL if no match is found. 

strstr()

This function performs a case-sensitive search for the first occurrence of one string within another string. Its prototype is

char *strstr(const char *str1, const char *str2);

The function strstr() returns a pointer to the first occurrence of str2 within str1 . If the search does not find a match, then the function returns NULL . When strstr() finds a match, the position of the substring can  be calculated by subtracting str from the pointer value returned by strchr(). 

The following short program demonstrates the strstr function

#include <stdio.h>
#include <string.h>
char str1[] = "123456789";
char str2[] = "56";
char *position;
int main( void )
{
 char *position;
position=strstr(str1, str2);
printf("\n%i ",position-str1);
return 0;
}

Characters and Strings

C uses the char type to store characters and letters. Char is considered an integer type. Each char integer value is mapped with a corresponding character using a numerical code. The most common numerical code is ASCII.

Declare a char

The char keyword is used to declare a character type variable followed by the variable name –

char ch;

Initialise a char

A char character variable can be initialised with a character literal or an integer type. A character literal contains one character surrounded by a single quotation (‘’).

The following example declares  a char variable character and initialises it with a character literal ‘a’

ch='a';

Because the type is the integer type, you can also initialise or assign a char variable using an integer. –

char ch=65;

Single quotes vs double quotes

In C, single quotes identify a single character; double quotes create a string array. ‘a’ represents a single character literal, while “a” is a string literal consisting of an ‘a’ and the null terminator ‘/0’. 

Print characters in C

To print characters in C, use the printf() function. The syntax for printf() is

int printf( const char* str, ... );

The string pointed to by str contains the data types to be printed on screen with the data type format specifiers proceeded with %. These are replaced by the variable values passed to the printf() function as additional arguments.

The printf function is not part of the C language but is found in the <stdio.h> header file

The following code example demonstrates how to print characters in C using both integers and char literals

#include "stdio.h"; /* Declare and initialise two char variables */
char c1 = 'A';
char c2 = 90;
int main( void ) { /* Print variable c1 as a character, then as a number */
printf("\nvariable c1 As a character, is %c", c1);
printf("\nvariable c1 As a number, is %d", c1); /* Do the same for variable c2 */
printf("\nvariable c2 As a character, is %c", c2);
printf("\nvariable c2 As a number, is %d\n", c2);
return 0;
}

Char Arrays

C-strings are arrays of type char terminated with null character or \0.

To declare and initialise a character string 

Character arrays can be declared and initialised on a character-by-character basis using an array-style initialiser however it’s much easier to initialise a character array with a string literal –

char greeting[6] = {'h','e','l','l','o','\0'} (array style initialiser with the NULL character being added manually)

char greeting[] = "hello" ;(initialisation with a string literal with the null character being added automatically.

Initialising a char array with the value ‘\0’ creates a NULL or empty string – 

char greeting[0] = {'\0'};

Inserting ‘\0’ anywhere in the middle of the array would not change the size of the array but it would mean that string processing would stop at that point. Sending the following to the char array to screen would only produce the characters ‘hel’

char greeting[] = "hel\0lo" 

Assign new values to a char array

To change the contents of the string after the initial assignment, it is necessary to change the array contents individually. Assigning the new value to the existing char array ie greetings[]=”HELLO” won’t work because the = operator isn’t defined to copy the contents of a string literal to an array.

greetings[0] = 'H';
greetings[1] = 'E';
greetings[2] = 'L';
greetings[3] = 'L';
greetings[4] = 'O';
greetings[5] = '\0';

Since assigning new array string values individually is not practical, C uses the strcpy or the strncpy function to assign the contents of an array outside of a declaration. The strcpy is found in the string.h header, The syntax for strcpy is-

strcpy(greetings,"hello");

Pointers and Arrays

Arrays elements can also be accessed by the use of pointers. The pointer is declared and assigned to the first element of the array. After assigning the array pointer, the individual elements can be accessed by increasing or decreasing the pointer value.

The code sample below outputs the same letters of an array string by using pointers and array indexing

#include "stdio.h"
int main()
{
char str[31]="this is a string to array test"; //declares char array
char *pChar=str; //declares char pointer and sets to start of array
int i;
for(i=0; i<=31; i++) {
printf("%c", *(pChar+i));//prints value of char array 
}
return 0;
}

Pointers and String Literals

A string literal is a constant null-terminated sequence of characters enclosed in double quotation marks. All C compilers create a read-only string table for storing these string literals. Programmers can allocate their own pointers to store and access characters held in string tables.

int main()
{
const char *ptrsl= "this is a string literal.\n"; //creates pointer ptrsl to to start of string array
printf (ptrsl);
return 0;
}

Attempting to modify a string literal using a pointer can result in undefined behaviour so any pointer to a string literal should be declared as const.

Array of Pointers

An array of pointers to strings is an array of character pointers where each pointer points to the first string character or base address of the string. To declare and initialise an array of pointers to strings –

char *day[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday","Friday","Saturday"};

Since initialisation of the array is done at the time of declaration we can omit the size of an array.

Each element of the day[] array is a string literal and since a string literal points to the base address of the first character, the base type of each element of the sports array is a pointer to char or (char*).

To access the values pointed to by an array of pointers it is necessary to iterate and dereference each pointer individually.

#include "stdio.h"
const int MAX = 7; 
int main () 
{ 
char *day[] = {"Sunday","Monday","Tuesday", "Wednesday", "Thursday","Friday","Saturday"}; 
for (int i = 0; i < MAX; i++) 
{ 
   printf("day[%d] = %s\n", i, day[i]);     
} 
return 0;
}

Arrays

An array is a data structure consisting of a collection of elements (values or variables) of the same data type. Each storage location in an array is called an array element and is identified by an array index or key. The lowest index address corresponds to the first element and the highest index address to the last element.

Declare an array

The declaration statement for an array is similar to a variable declaration with the exception that the number of array elements is specified inside square brackets after the array name –

int example[5];

The example array (above) declares 5 sequential integers. This declaration causes the compiler to set aside enough memory to hold all 5 int elements. The array element number is also is called the array subscript.

Initialising Arrays

Arrays can be initialised when they are first declared by use of the equal sign followed by a list of values enclosed in braces and separated by commas:

int example[5]= { 10, 20, 30, 40, 50 };

In the example above, the value 10 is assigned to example[0], the value 20 is assigned to example[1], the value 30 is assigned to the example[2], the value 40 is assigned to example[3]  and the value 50 is assigned to example[4].  If the array size is omitted, the compiler creates an array large enough to hold the initialisation values. The following statement would have the same effect as the previous array declaration statement:

int example[] = { 10, 20, 30, 40, 50 };

Although the number of initialisation values can be fewer than the number of array elements, too many initialisers ie more initialisers than array elements will cause the compiler to generate an error. Any array element not initialised will contain an unknown value

Multidimensional array

A multidimensional array has more than one subscript. A two-dimensional array has two subscripts and a three-dimensional array has three subscripts.  There is no limit to the number of C array dimensions although the size of an array will be limited by the amount of memory on the computer. The following declaration for a two-dimensional array will be able to hold 64 int values

int example[8][8];

Multidimensional arrays can also be initialised by assigning array elements in order. For
example:

int array[2][4] = { 1, 2, 3, 4, 5, 6, 7, 8 };

which can also be written

array[2][4]={{1,2,3,4},{5,6,7,8}};

results in the following assignments:

array[0][0]=1
array[0][1]=2
array[0][2]=3
array[0][3]=4
array[1][0]=5
array[1][1]=6
array[1][2]=7
array[1][3]=8

Accessing Data Stored in an Array

An element is accessed by indexing the array name. This is done by placing the element index within square brackets after the array name. These indexes are called zero-based because the first element in an array is at index 0. The first integer value stored in an array arraydata[10] is arraydata[0] , the second is arraydata[1] , and so on. The index of the last element in an array is always (Length of Array – 1) or arraydata[9].