Sunday, 28 April 2019

C Programming Language in 2019

In four years’ time, C will reach its 50th birthday, an anniversary also shared with PL/M and Prolog. Unlike those two, C remains immensely popular, it’s in the top ten of virtually every programming language popularity survey.

Linux is mostly written in C. Python‘s CPython implementation, Perl, Matz’s Ruby, about half of R, the MyISAM code for MySQL and even the first Java compiler were all written in C. The kernels of most operating systems (including Windows, Mac, Linux, iOS and Android) all feature C.

Now we have a new C standard, C18, that was ratified a few months ago. A mere 198 Swiss Francs will buy the ISO/IEC 9899:2018 standard, all 520 pages of it; you can view the final draft of it for free, though, on openStd.org (PDF) to get a sense of the document. It’s only really of use if you are a compiler writer who wants to be 100 percent conformant, or just curious.

There’s nothing new in C18, just more fixes, so it’s very much a continuation of C17. The last major changes to C were in C11, and those included variable length arrays, multi-threading support, better Unicode support, anonymous structures and unions, and a lot more.

C Holds Its Own Against C++
C++ has made some inroads into C’s arena, especially since the C++ move semantics were added in C++11. When used in the right way, particularly with pointers to large objects, this results in better performance, fewer temporary copies, and lets C++ be used in places that were traditionally C territory (e.g., embedded).

However, C++ compiled code is still generally a bit larger than that of C, because exception handling adds bulk and the number of inline template classes whose members get included.

Out of curiosity, I compiled this in release mode in Visual C++ 2017:

#include
int main()
{
    std::cout << "Hello world" << std::endl;
    return 0;
}
That compiled to a 10,752 bytes exe. The equivalent C program is:

#include
int main()
{
    printf("hello world\n");
    return 0;
}


That was 9,216 bytes long, or 85 percent of the size. Not a great deal of difference, but I could project this difference growing once you add in other classes.

Code size is important because of the increasing number of Internet of Things (IoT) devices and the use of microcontrollers, which typically have RAM and ROM (Flash) measured in kilobytes. In the embedded field, C has actually gained market share between 2005 and 2018.

C is the Lingua Franca of Programming
C is the programming “common language.” Many programming-language compilers output C source code and let a C compiler do the heavy lifting of generating code (there are around 60 open-source compilers listed on this Github project page; there are also a few targeting C++, as well, but the C ones dominate). It’s not difficult to understand, as C is the lowest-level portable language (the only one lower, assembly language, is tied to a CPU family).

Using C to Speed Up Languages
One of the most popular languages, standard Python, suffers from speed issues because of its interpreted code and use of dynamic variables. If you are doing numeric processing, then you’ll be aware of the likes of NumPy, SciPy, and so on. NumPy is written in C. The standard implementation of Python is CPython, and so works well with libraries in C (and C++).

An alternative way to speed up Python is by using one of the compilers such as Cython, PyPy, or Nuitka. Read about Python compilers speed tests.

C is Recognized as a Useful-to-Know Language
It’s probably not the first language any programmer wants to learn, but it appears to be popular as a second or third alternative. I’ve also seen it as a stepping-stone to learning C++, which is a superset of C.

It’s a matter of debate whether C++ is in decline, but C is by far the easier to learn of the two languages.

Conclusion
C has definitely earned its place as an infrastructure programming language. There is so much software out there that’s used every day, particularly on Linux, that C will be around for a very long time.

Even though Go and Rust in particular are modern and better languages, C is so embedded in the infrastructure of the internet that I doubt it will ever be replaced. Over half of all active web servers are running Apache and Nginx, both written in C (according to Netcraft).It’s been around for almost 50 years, but C very much has a future.

Friday, 24 February 2017

COMMAND LINE ARGUMENTS

COMMAND LINE ARGUMENTS

It is possible to pass some values from the command line to your C programs
when they are executed. These values are called command line
arguments and many times they are important for your program especially
when you want to control your program from outside instead of hard coding
those values inside the code.

The command line arguments are handled using main() function arguments
where argc refers to the number of arguments passed, and argv[] is a pointer
array which points to each argument passed to the program. Following is a
simple example which checks if there is any argument supplied from the
command line and take action accordingly:

#include <stdio.h>
int main( int argc, char *argv[] )
{
if( argc == 2 )
{
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 )
{
printf("Too many arguments supplied.\n");
}
else
{
printf("One argument expected.\n");
}
}

When the above code is compiled and executed with a single argument, it
produces the following result.

$./a.out testing
The argument supplied is testing

30. COMMAND LINE ARGUMENTS

When the above code is compiled and executed with two arguments, it produces
the following result.

$./a.out testing1 testing2
Too many arguments supplied.

When the above code is compiled and executed without passing any argument,
it produces the following result.

$./a.out
One argument expected

It should be noted that argv[0] holds the name of the program itself
and argv[1] is a pointer to the first command line argument supplied, and
*argv[n] is the last argument. If no arguments are supplied, argc will be one,
and if you pass one argument, then argc is set at 2.
You pass all the command line arguments separated by a space, but if argument
itself has a space then you can pass such arguments by putting them inside
double quotes "" or single quotes ''. Let us re-write above example once again
where we will print program name and we also pass a command line argument
by putting inside double quotes:

#include <stdio.h>
int main( int argc, char *argv[] )
{
printf("Program name %s\n", argv[0]);
if( argc == 2 )
{
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 )
{
printf("Too many arguments supplied.\n");
}
else
{
printf("One argument expected.\n");
}
}

When the above code is compiled and executed with a single argument
separated by space but inside double quotes, it produces the following result.

$./a.out "testing1 testing2"
Progranm name ./a.out
The argument supplied is testing1 testing2


MEMORY MANAGEMENT

MEMORY MANAGEMENT

This chapter explains dynamic memory management in C. The C programming
language provides several functions for memory allocation and management.
These functions can be found in the <stdlib.h> header file.


Function and Description

1 void *calloc(int num, int size);
This function allocates an array of num elements each of which size in
bytes will be size.

2 void free(void *address);
This function releases a block of memory block specified by address.

3 void *malloc(int num);
This function allocates an array of num bytes and leave them initialized.

4 void *realloc(void *address, int newsize);
This function re-allocates memory extending it upto newsize.

Allocating Memory Dynamically

While programming, if you are aware of the size of an array, then it is easy and
you can define it as an array. For example, to store a name of any person, it can
go up to a maximum of 100 characters, so you can define something as follows:

char name[100];

But now let us consider a situation where you have no idea about the length of
the text you need to store, for example, you want to store a detailed description
about a topic. Here we need to define a pointer to character without defining
how much memory is required and later, based on requirement, we can allocate
memory as shown in the below example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char name[100];
char *description;
strcpy(name, "Zara Ali");
/* allocate memory dynamically */
description = malloc( 200 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcpy( description, "Zara ali a DPS student in class 10th");
}
printf("Name = %s\n", name );
printf("Description: %s\n", description );
}

When the above code is compiled and executed, it produces the following result.

Name = Zara Ali
Description: Zara ali a DPS student in class 10th

Same program can be written using calloc(); only thing is you need to replace
malloc with calloc as follows:

calloc(200, sizeof(char));

So you have complete control and you can pass any size value while allocating
memory, unlike arrays where once the size is defined, you cannot change it.

Resizing and Releasing Memory

When your program comes out, operating system automatically release all the
memory allocated by your program but as a good practice when you are not in
need of memory anymore then you should release that memory by calling the
function free().

Alternatively, you can increase or decrease the size of an allocated memory
block by calling the function realloc(). Let us check the above program once
again and make use of realloc() and free() functions:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char name[100];
char *description;
strcpy(name, "Zara Ali");
/* allocate memory dynamically */
description = malloc( 30 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcpy( description, "Zara ali a DPS student.");
}
/* suppose you want to store bigger description */
description = realloc( description, 100 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcat( description, "She is in class 10th");
}
printf("Name = %s\n", name );
printf("Description: %s\n", description );
/* release memory using free() function */
free(description);
}

When the above code is compiled and executed, it produces the following result.

Name = Zara Ali
Description: Zara ali a DPS student.She is in class 10th


You can try the above example without re-allocating extra memory, and strcat()
function will give an error due to lack of available memory in description.

VARIABLE ARGUMENTS

VARIABLE ARGUMENTS

Sometimes, you may come across a situation, when you want to have a
function, which can take variable number of arguments, i.e., parameters,
instead of predefined number of parameters. The C programming language
provides a solution for this situation and you are allowed to define a function
which can accept variable number of parameters based on your requirement.
The following example shows the definition of such a function.

int func(int, ... )
{
.
.
.
}
int main()
{
func(1, 2, 3);
func(1, 2, 3, 4);
}


It should be noted that the function func() has its last argument as ellipses,
i.e., three dotes (...) and the one just before the ellipses is always an int which
will represent the total number variable arguments passed. To use such
functionality, you need to make use of stdarg.h header file which provides the
functions and macros to implement the functionality of variable arguments and
follow the given steps:

1. 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.

2. Create a va_list type variable in the function definition. This type is
defined in stdarg.h header file.

3. Use int parameter and va_start macro to initialize the va_list variable to
an argument list. The macro va_start is defined in stdarg.h header file.

4. Use va_arg macro and va_list variable to access each item in argument
list.

5. Use a macro va_end to clean up the memory assigned
to va_list variable.

Now let us follow the above steps and write down a simple function which can
take the variable number of parameters and return their average:

#include <stdio.h>
#include <stdarg.h>
double average(int num,...)
{
va_list valist;
double sum = 0.0;
int i;
/* initialize valist for num number of arguments */
va_start(valist, num);
/* access all the arguments assigned to valist */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* clean memory reserved for valist */
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));
}


When the above code is compiled and executed, it produces the following result.
It should be noted that the function average() has been called twice and each
time the first argument represents the total number of variable arguments being
passed. Only ellipses will be used to pass variable number of arguments.

Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000


RECURSION


RECURSION

Recursion is the process of repeating items in a self-similar way. In
programming languages, if a program allows you to call a function inside the
same function, then it is called a recursive call of the function.


void recursion()
{
recursion(); /* function calls itself */
}
int main()
{
recursion();
}

The C programming language supports recursion, i.e., a function to call itself.
But while using recursion, programmers need to be careful to define an exit
condition from the function, otherwise it will go into an infinite loop.


Recursive functions are very useful to solve many mathematical problems, such
as calculating the factorial of a number, generating Fibonacci series, etc.


Number Factorial

The following example calculates the factorial of a given number using a
recursive function:

#include <stdio.h>
int factorial(unsigned int i)
{
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1);
}
int main()
{
int i = 15;
printf("Factorial of %d is %d\n", i, factorial(i));
return 0;
}

When the above code is compiled and executed, it produces the following result:

Factorial of 15 is 2004310016


Fibonacci Series


The following example generates the Fibonacci series for a given number using a
recursive function:

#include <stdio.h>
int fibonaci(int i)
{
if(i == 0)
{
return 0;
}
if(i == 1)
{
return 1;
}
return fibonaci(i-1) + fibonaci(i-2);
}
int main()
{
int i;
for (i = 0; i < 10; i++)
{
C Programming
166
printf("%d\t%n", fibonaci(i));
}
return 0;
}

When the above code is compiled and executed, it produces the following result:

0 1 1 2 3 5 8 13 21 34


ERROR HANDLING

ERROR HANDLING

As such, C programming does not provide direct support for error handling but
being a sytem programming language, it provides you access at lower level in
the form of return values. Most of the C or even Unix function calls return -1 or
NULL in case of any error and set an error code errno. It is set as a global
variable and indicates an error occurred during any function call. You can find
various error codes defined in <error.h> header file.

So a C programmer can check the returned values and can take appropriate
action depending on the return value. It is a good practice to set errno to 0 at
the time of initializing a program. A value of 0 indicates that there is no error in
the program.

errno, perror(), and strerror()

The C programming language provides perror() and strerror() functions which
can be used to display the text message associated with errno.

· The perror() function displays the string you pass to it, followed by a
colon, a space, and then the textual representation of the current errno
value.

· The strerror() function, which returns a pointer to the textual
representation of the current errno value.

Let's try to simulate an error condition and try to open a file which does not
exist. Here I'm using both the functions to show the usage, but you can use one
or more ways of printing your errors. Second important point to note is that you
should use stderr file stream to output all the errors.

#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ;
int main ()
{
FILE * pf;
int errnum;
pf = fopen ("unexist.txt", "rb");
if (pf == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("Error printed by perror");
fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
}
else
{
fclose (pf);
}
return 0;
}


When the above code is compiled and executed, it produces the following result:

Value of errno: 2
Error printed by perror: No such file or directory
Error opening file: No such file or directory

Divide byZero Errors


It is a common problem that at the time of dividing any number, programmers
do not check if a divisor is zero and finally it creates a runtime error.
The code below fixes this by checking if the divisor is zero before dividing:

#include <stdio.h>
#include <stdlib.h>
main()
{
int dividend = 20;
int divisor = 0;
int quotient;
if( divisor == 0){
fprintf(stderr, "Division by zero! Exiting...\n");
exit(-1);
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient );
exit(0);
}

When the above code is compiled and executed, it produces the following result:

Division by zero! Exiting...

Program Exit Status


It is a common practice to exit with a value of EXIT_SUCCESS in case of
program coming out after a successful operation. Here, EXIT_SUCCESS is a
macro and it is defined as 0.
If you have an error condition in your program and you are coming out then you
should exit with a status EXIT_FAILURE which is defined as -1. So let's write
above program as follows:


#include <stdio.h>
#include <stdlib.h>
main()
{
int dividend = 20;
int divisor = 5;
int quotient;
if( divisor == 0){
fprintf(stderr, "Division by zero! Exiting...\n");
exit(EXIT_FAILURE);
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient );
exit(EXIT_SUCCESS);
}


When the above code is compiled and executed, it produces the following result:

Value of quotient : 4



TYPE CASTING

TYPE CASTING

Type casting is a way to convert a variable from one data type to another data
type. For example, if you want to store a ‘long’ value into a simple integer, then
you can type cast ‘long’ to ‘int’. You can convert the values from one type to
another explicitly using the cast operator as follows:

(type_name) expression

Consider the following example where the cast operator causes the division of
one integer variable by another to be performed as a floating-point operation:

#include <stdio.h>
main()
{
int sum = 17, count = 5;
double mean;
mean = (double) sum / count;
printf("Value of mean : %f\n", mean );
}

When the above code is compiled and executed, it produces the following result:

Value of mean : 3.400000

It should be noted here that the cast operator has precedence over division, so
the value of sum is first converted to type double and finally it gets divided by
count yielding a double value.

Type conversions can be implicit which is performed by the compiler
automatically, or it can be specified explicitly through the use of the cast
operator. It is considered good programming practice to use the cast operator
whenever type conversions are necessary.


Integer Promotion

Integer promotion is the process by which values of integer type "smaller"
than int or unsigned int are converted either to int or unsigned int. Consider
an example of adding a character with an integer:


#include <stdio.h>
main()
{
int i = 17;
char c = 'c'; /* ascii value is 99 */
int sum;
sum = i + c;
printf("Value of sum : %d\n", sum );
}

When the above code is compiled and executed, it produces the following result:

Value of sum : 116

Here, the value of sum is 116 because the compiler is doing integer promotion
and converting the value of 'c' to ASCII before performing the actual addition
operation.

Usual Arithmetic Conversion


The usual arithmetic conversions are implicitly performed to cast their values
to a common type. The compiler first performs integer promotion; if the
operands still have different types, then they are converted to the type that
appears highest in the following hierarchy:

The usual arithmetic conversions are not performed for the assignment
operators, nor for the logical operators && and ||. Let us take the following
example to understand the concept:
#
include <stdio.h>
main()
{
int i = 17;
char c = 'c'; /* ascii value is 99 */
float sum;
sum = i + c;
printf("Value of sum : %f\n", sum );
}

When the above code is compiled and executed, it produces the following result:

Value of sum : 116.000000

Here, it is simple to understand that first c gets converted to integer, but as the
final value is double, usual arithmetic conversion applies and the compiler
converts i and c into ‘float’ and adds them yielding a ‘float’ result.