egsoftweb@gmail.com
 facebook.com/egsoftweb

Introduction to C programming

 c tutorials |  Admin

History of C

C was invented and first implemented by Dennis Ritchie on a DEC PDP-11 that used the UNIX operating system.

C is the result of a development process that started with an older language called BCPL.

BCPL was developed by Martin Richards, and it influenced a language called B, which was invented by Ken Thompson. B led to the development of C in the 1970s.

OR

C is a programming language developed at AT & T’s Bell Laboratories of USA in 1972. It was designed and written by a man named Dennis Ritchie. In the late seventies C began to replace the more familiar languages of that time like PL/I, ALGOL, etc. No one pushed C. It wasn’t made the ‘official’ Bell Labs language. Thus, without any advertisement C’s reputation spread and its pool of users grew. Ritchie seems to have been rather surprised that so many programmers preferred C to older languages like FORTRAN or PL/I, or the newer ones like Pascal and APL.

C Is a Middle-Level Language

C is thought of as a middle-level language because it combines the best elements of high-level languages with the control and flexibility of assembly language.

Highest level

Ada

 

Modula-2

 

Pascal

 

COBOL

 

FORTRAN

 

BASIC

 

 

Middle level

Java

 

C#

 

C++

 

C

 

Forth

 

Macro-assembler

 

 

Lowest level

Assembler

 

Initially, C was used for systems programming. A systems program forms a portion of the operating system of the computer or its support utilities, such as editors, compilers, linkers, and the like. As C grew in popularity, many programmers began to use it to program all tasks because of its portability and efficiency- and because they liked it! At the time of its creation, C was a much longed-for, dramatic improvement in programming languages. In the years that have since elapsed, C has proven that it is up to any task.

Difference between Compiler and Interpreter

In its simplest form, an interpreter reads the source code of your program one line at a time, performing the specific instructions contained in that line. This is the way earlier versions of BASIC worked. In languages such as Java, a program`s source code is first converted into an intermediary form that is then interpreted. In either case, a run-time interpreter is still required to be present to execute the program.

A compiler reads the entire program and converts it into object code, which is a translation of the program`s source code into a form that the computer can execute directly. Object code is also referred to as binary code or machine code. Once the program is compiled, a line of source code is no longer meaningful in the execution of your program.

Keywords in C

Keywords are predefined, reserved words used in programming that have special meanings to the compiler. Keywords are part of the syntax and they cannot be used as an identifier. Below is the list of c keywords:

auto

break

case

char

const

continue

default

do

double

else

enum

extern

float

for

goto

if

int

long

register

return

short

signed

sizeof

static

struct

switch

typedef

union

unsigned

void

volatile

while

 

 

Linker

A linker is a computer program that takes one or more object files generated by a compiler and combines them into one, executable program.

 

The Form of a C Program

Global declarations

int main(parameter list)

{

      statement sequence

}

return-type f1(parameter list)

{

      statement sequence

}

 

return-type f2(parameter list)

{

      statement sequence

}

. . .

return-type fN(parameter list)

      statement sequence

}

 

C, C99, ANSI C and GNU C

 c tutorials |  Admin

Difference between C, C99, ANSI C and GNU C:

 

Everything before standardization is generally called "K&R C", after the famous book, with Dennis Ritchie, the inventor of the C language, as one of the authors. This was "the C language" from 1972-1989.

 

The first C standard was released 1989 nationally in USA, by their national standard institute ANSI. This release is called C89 or ANSI-C. From 1989-1990 this was "the C language".

 

The year after, the American standard was accepted internationally and published by ISO (ISO 9899:1990). This release is called C90. Technically, it is the same standard as C89/ANSI-C. Formally, it replaced C89/ANSI-C, making them obsolete. From 1990-1999, C90 was "the C language".

 

Please note that since 1989, ANSI haven`t had anything to do with the C language. Programmers still speaking about "ANSI C" generally haven`t got a clue about what it means. ISO "owns" the C language, through the standard ISO 9899.

 

A minor update was released in 1995, sometimes referred to as "C95". This was not a major revision, but rather a technical amendment formally named ISO/IEC 899:1990/Amd.1:1995. The main change was introduction of wide character support.

 

In 1999, the C standard went through a major revision (ISO 9899:1999). This version of the standard is called C99. From 1999-2011, this was "the C language".

 

In 2011, the C standard was changed again (ISO 9899:2011). This version is called C11. Various new features like _Generic, _Static_assert and thread support were added to the language. The update had a lot of focus on multi-core, multi-processing and expression sequencing. From 2011-2017, this was "the C language".

 

In 2017, C11 was revised and various defect reports were solved. This standard is informally  called C17 and was released as ISO 9899:2018. It contains no new features, just corrections. It is the current version of the C language.

 

"C99 strict" likely refers to a compiler setting forcing a compiler to follow the standard by the letter. There is a term conforming implementation in the C standard. Essentially it means: "this compiler actually implements the C language correctly". Programs that implement the C language correctly are formally called strictly conforming programs.

 

"GNU C" can mean two things. Either the C compiler itself that comes as part of the GNU Compiler Collection (GCC). Or it can mean the non-standard default setup that the GCC C compiler uses. If you compile with gcc program.c then you don`t compile according to the C standard, but rather a non-standard GNU setup, which may be referred to as "GNU C". For example, the whole Linux kernel is made in non-standard GNU C, and not in standard C.

 

If you want to compile your programs according to the C standard, you should type gcc -std=c99 -pedantic-errors. Replace c99 with c11 if your GCC version supports it.

The Basic Data Types

 c tutorials |  Admin


Data type`s keyword

Data type

char

character

int

integer

float

floating-point

double

double floating-point

void

valueless

C89 five foundational data types:

 

These types form the basis for several other types. The size and range of these data types may vary among processor types and compilers. However, in all cases an object of type char is 1 byte. The size of an int is usually the same as the word length of the execution environment of the program.

 

For most 16-bit environments, such as DOS or Windows 3.1, an int is 16 bits. For most 32-bit environments, such as Windows 95/98/NT/2000, an int is 32 bits. However, you cannot make assumptions about the size of an integer if you want your programs to be portable to the widest range of environments. It is important to understand that C stipulates only the minimal range of each data type, not its size in bytes.

 

The use of signed on integers is allowed, but it is redundant because the default integer declaration assumes a signed number. The most important use of signed is to modify char in implementations in which char is unsigned by default.

 

Signed and unsigned integers differ in the way that the high-order bit of the integer is interpreted. If you specify a signed integer, the compiler generates code that assumes the high-order bit of an integer is to be used as a sign flag. If the sign flag is 0, the number is positive; if it is 1, the number is negative.

 

If the high-order bit were set to 1, the number would be interpreted as –1. However, if you declare this to be an unsigned int, the number becomes 65,535 when the high-order bit is set to 1.

 

When a type modifier is used by itself (that is, when it does not precede a basic type), then int is assumed. Thus, the following sets of type specifiers are equivalent:

 

Specifier

Same As

signed

signed int

unsigned

unsigned int

long

long int

short

short int

 

Although the int is implied, it is common practice today to specify the int anyway.

 

Note: To the five basic data types defined by C89, C99 adds three more:

_Bool, _Complex, and _Imaginary.

 

 

Here simple code is given to print data type`s size and range.  Right shift is used for calculating powers of 2 to get range and `sizeof` operator is used for calculation of size. 

Identifier Names & Variables

 c tutorials |  Admin

Identifier Names:

The names of variables, functions, labels, and various other user-defined items are called identifiers.

The length of these identifiers can vary from one to several characters.

The first character must be a letter or an underscore, and subsequent characters must be either letters, digits or underscores.

Correct

Incorrect

i1

1i

a23     

23a

low_count

low..count

helloWorld

hello!World

correct and incorrect identifier names

 

In C, identifiers may be of any length. However, not all characters will necessarily be significant.

C defines two kinds of identifiers: external and internal.

An external identifier will be involved in an external link process. These identifiers, called external names, include function names and global variable names that are shared between source files. If the identifier is not used in an external link process, then it is internal. This type of identifier is called an internal name and includes the names of local variables. For example, in C89, at least the first 6 characters of an external identifier and at least the first 31 characters of an internal identifier will be significant. C99 has increased these values.

In C99, an external identifier has at least 31 significant characters, and an internal identifier has at least 63 significant characters. As a point of interest, in C++, at least the first 1,024 characters of an identifier are significant. These differences may be important if you are converting a program from C89 to C99, or from C to C++.

In an identifier, upper- and lowercase are treated as distinct. Hence, count, Count, and COUNT are three separate identifiers.

An identifier cannot be the same as a C keyword and should not have the same name as functions that are in the C library.


Variables:

A variable is a named location in memory that is used to hold a value that can be modified by the program.

All variables must be declared before they can be used.

The general form of a declaration is

type variable_list;

Here, type must be a valid data type plus any modifiers, and variable_list may consist of one or more identifier

names separated by commas. Here are some declarations:

int i, j, l;

short int si;

unsigned int ui;

double balance, profit, loss;

In C the name of a variable has nothing to do with its type

 

Types of variables:

Local variables:  Variables that are declared inside a function.

Variables as formal parameters: A function`s parameters are known as variables that will accept the values of the arguments.

Global variables: Global variables are known throughout the program and may be used by any piece of code. Also, they will hold their value throughout the program`s execution. You create global variables by declaring them outside of any function. Any expression may access them, regardless of what block of code that expression is in.

Scope, Declaration & Definition

 c tutorials |  Admin

C Language Scope

A scope is a region of the program where a defined object can have its existence and beyond that, object cannot be accessed. There are three places where variables can be declared in C programming language.

 

Local variables

Inside a function or a block

Global variables

outside of all functions

Formal parameters

In the definition of function parameters

 

Standard C defines four scopes that determine the visibility of an identifier.

 

File scope: Starts at the beginning of the file, ends with the end of the file.  Refers only to those identifiers that are declared outside of all functions. e.g. global variables have this scope.

 

Block scope: Starts with the opening {, ends with its associated closing }. However, block scope also extends to function parameters in a function definition. That is, function parameters are included in a function`s block scope. Variables with block scope are local to their block.

 

Function prototype scope: Identifiers declared in a function prototype (function prototype is also called as function declaration); visible within the prototype.

 

Function scope: Begins with the opening { of a function and ends with its closing }. Function scope applies only to labels. A label is used as the target of a goto statement, and that label must be within the same function as the goto.

 

 

Declaration & Definition:

 

Declaration:  A declaration declares the name and type of an object.

Definition:  A definition causes storage to be allocated for the object.

 

Same object may have many declarations, but there can be only one definition.  It is better to declare all functions in a header file and including it (using #include) in a source file (c file) in which we can put their definitions.


In the below a code is given to clarify the above.

Storage Class Specifiers

 c tutorials |  Admin

C supports four storage class specifiers:

 

extern

static

register

auto

 

These specifiers tell the compiler how to store a variable in memory.  The general form of a variable declaration is:

storage_specifier type var_name;

 

Note: Both C89 and C99 state that typedef is a storage class specifier for the purposes of syntactic convenience, but it is not a storage class specifier in the common meaning of the term.

 

extern:

C defines three categories of linkage: external, internal, and none. Functions and global variables have external linkage. It means they are available to all files that constitute a program.  File scope objects declared as static have internal linkage. These are known only within the file in which they are declared.

 

Local variables have no linkage and are therefore known only within their own block.

 

The principal use of extern is to specify that an object is declared with external linkage elsewhere in the program.

 

Variable declarations are definitions.  However, by preceding a variable name with the extern specifier, you can declare a variable without defining it.

 

Thus, when you need to refer to a variable that is defined in another part of your program, you can declare that variable using extern.

 

Note: note-extern can also be applied to a function declaration, but doing so is redundant.

 

// example using extern

#include <stdio.h>

int main(void)

{

            extern int var1, var2; /* use global vars */

            printf("%d %d", var1, var2);

            getchar();

            return 0;

}

/* global definition of first and last */

int var1 = 100, var2 = 200;

 

 

In this example the extern declaration tells the compiler that first and last are declared elsewhere (in this case, later in the same file), the program can be compiled without error even though first and last are used prior to their definition. If the global variables var1 and var2 would be defined prior to main function there would have been no need for the extern statement.

 

// file1.c

int ig1, ig2;

char ic;

int main(void)

{

            /* . . . */

}

void func1(void)

{

            ig1 = 123;

}

 

// file2.c

extern int ig1, ig2;

extern char ic;

void func2(void)

{

            ig1 = ig2 / 10;

}

void func3(void)

{

            ig2 = 10;

}

Another example using extern-

 

Here in file2.c, the global variable list was copied from file1.c, and the extern specifier was added to the declarations. The extern specifier tells the compiler that the variable types and names that follow it have been defined elsewhere. In other words, extern lets the compiler know what the types and names are for these global variables without actually creating storage for them again. When the linker links the two modules, all references to the external variables are resolved.

For simplicity, we can put extern declarations normally in a header file that is simply included with each source code file. This is both easier and less error prone than manually duplicating extern declarations in each file.

 

static:

static Variables- Variables declared as static are permanent variables within their own function or file. Unlike global variables, they are not known outside their function or file, but they maintain their values between calls. This feature makes them useful when we write generalized functions and function libraries that other programmers may use. The static modifier has different effects upon local variables and global variables.

 

static Local Variables- When we apply the static modifier to a local variable, the compiler creates permanent storage for it, much as it creates storage for a global variable. The key difference between a static local variable and a global variable is that the static local variable remains known only to the block in which it is declared. In simple terms, a static local variable is a local variable that retains its value between function calls.

 

static Global Variables- Applying the specifier static to a global variable instructs the compiler to create a global variable known only to the file in which it is declared. Thus, a static global variable has internal linkage (as described under the extern statement). It means that even though the variable is global, routines in other files have no knowledge of it and cannot alter its contents directly, keeping it free from side effects. For the few situations where a local static cannot do the job, we can create a small file that contains only the functions that need the global static variable, separately compile that file, and use it without fear of side effects.

 

By using static variables, we can hide portions of our program from other portions. It can be a tremendous advantage when we are trying to manage a very large and complex program.

 

From Wikipedia:

In the C programming language, static is used with global variables and functions to set their scope to the containing file. In local variables, static is used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.

 

// example using static Local

int func(void)

{

            static int static_num = 0;

            static_num = static_num + 10;

            return static_num;

}

 

#include <stdio.h>

int main()

{

            int s1 = func();

            int s2 = func();

 

            printf("%d %d", s1, s2);

            getchar();

            return 0;

}

 

// example using static Global

static float static_pi;

float getCircleArea(float radius);

void initPI();

 

float getCircleArea(float radius)

{

            initPI();

            float area = static_pi*radius*radius;

            return area;

}

 

void initPI()

{

            static_pi = 3.1415296;

}

 

example using static

 

In the example using static local, the variable static_num stays in existence between function calls, instead of coming and going the way a normal local variable would. This means that each call to func( ) can produce a new value of static_num based on the preceding value without declaring that it globally. You can give a static local variable an initialization value. This value is assigned only once, at program start-up, not each time the block of code is entered, as with normal local variables.

 

In the example using static Global, the global static integer variable static_pi is known only in the file in which it is declared. We can access static_pi in other files only by including the file by (#include ) where static_pi has it`s declaration.  

 

register:

The register storage specifier originally applied only to variables of type int, char, or pointer types. However, in Standard C, register`s definition has been broadened so that it can be applied to any type of variable.