Fundamentals of C

Background/History

C programming, developed by Dennis Ritchie at Bell Labs in the early 1970s, played a pivotal role in the history of computing. It evolved from the B programming language, to improve the portability and efficiency of software. The key events in its history include:

Creation of C (Early 1970s): Dennis Ritchie and his colleagues created C as a general-purpose programming language, allowing for more structured and efficient coding than its predecessor, B.

UNIX Development (Early 1970s): C became an integral part of the UNIX operating system's development, enabling its portability across different hardware platforms.

K&R C (1978): Ritchie and Brian Kernighan published "The C Programming Language," commonly referred to as K&R C, which established the language's syntax, concepts, and usage. This book became a foundational resource for programmers.

ANSI C Standardization (1983-1989): The American National Standards Institute (ANSI) developed a standardized version of C, known as ANSI C or C89. This standardization helped establish C's widespread adoption and portability across different compilers and systems.

C90 Standard (1990): Building on ANSI C, the International Organization for Standardization (ISO) released the C90 standard, further solidifying C's features and specifications.

C99 Standard (1999): The ISO introduced the C99 standard, which brought enhancements to the language, such as improved support for complex numbers, variable-length arrays, and inline functions.

C11 Standard (2011): The C11 standard introduced new features, including multi-threading support, atomic operations, and improved type-generic macros.

UNIX OS Development in C

UNIX development in C was a significant milestone in the history of computing. UNIX, an operating system created in the late 1960s and early 1970s by Ken Thompson and Dennis Ritchie at Bell Labs, was one of the first operating systems to be largely developed using the C programming language. Here's an overview of UNIX development in C:

Transition from Assembly Language: Before UNIX, operating systems were often developed using assembly languages specific to each hardware platform. This made porting software across different machines a cumbersome process. C's design allowed for writing system-level code that could be compiled on various hardware architectures with minimal modifications.

Porting UNIX: As C code could be compiled on different machines, the task of porting UNIX to new hardware architectures became much easier. This played a significant role in UNIX's rapid expansion to various platforms.

Rewriting in C: In the early stages of UNIX development, portions of the operating system were rewritten in C. This transition provided the developers with a common programming language that could be used across different parts of the system.

Kernel and System Software: The core of the UNIX operating system, including the kernel and system utilities, was written in C. This decision highlighted the language's ability to handle low-level operations and interact directly with hardware components.

Legacy and Influence: UNIX's development in C left an enduring legacy. Many modern operating systems and software projects are still influenced by the ideas and design principles introduced by UNIX and the use of a high-level language like C.


Literals

A literal is a representation of a fixed, unchanging value within the source code. It can be a value of a specific data type, such as numbers (integers or floating-point), characters, or strings.Literals are constants and do not change during program execution.Examples in C: 42 (integer literal), 3.14 (floating-point literal), 'A' (character literal), "Hello" (string literal).


Statements 

A statement is a complete instruction that performs a specific action or set of actions. It is the fundamental building block of a program and is used to express computations, assignments, control flow, and other operations. A statement in C typically ends with a semicolon (;) to indicate the termination of the instruction. It can be as simple as a single expression or as complex as a compound statement, which consists of multiple statements enclosed within curly braces ({}) and is often used for control flow structures like loops and conditional statements.

Here are some examples of C statements:

Return Statement: This statement returns the value from a function.

#include<stdio.h>
int main()
{
    return 0;   //return statement
}

Assignment Statement: The value 10 is assigned to a variable named x using an assignment statement.

#include<stdio.h>
int main()
{
    int x;
    x = 10; //assignment statement
    return 0;
}

Function call statement: printf("Hello, World!"); is a function call statement that displays Hello, World! as an output.

#include<stdio.h>
int main()
{
    printf("Hello, World!"); //function call statement
    return 0;
}

Loop statement: This statement is used to repeatedly execute a certain block of instructions.

#include<stdio.h>
int main()
{
    int i;
    for(i = 0; i < 5; i++) //loop statement
    {
        printf("%d\n", i);
    }
    return 0;
}

Conditional statement: This statement executes the selected part of a block using a condition.

#include <stdio.h>
int main()
{
    int x = 7;
    if (x > 0) //conditional statement
    {
        printf("x is positive");
    } 
    else 
    {
        printf("x is non-positive");
    }
    return 0;
}

Expression Statement: This statement evaluates the expression and updates the value of 'x'.

#include<stdio.h>
int main()
{
    int x = 1, y= 2, z;
    z = x + y;   //expression statement
    return 0;
}

Switch Statement: This statement executes a certain block of case based on switch condition.

#include<stdio.h>
int main()
{
    int x;
    printf("\nEnter x: ");
    scanf("%d", &x);

    switch (x)    //switch statement
    {
        case 1:
            printf("Value of x is 1");
            break;
        case 2:
            printf("Value of x is 2");
            break;
        default:
            printf("Value of x is neither 1 nor 2");
   }
    return 0;
}

Goto Statement: goto statement allows you to transfer control unconditionally from one part of the code to another.

#include <stdio.h>

int main() 
{
    int i = 1;

    // Using a label for the goto statement
    start:

    if (i <= 5) 
    {
        printf("%d ", i);
        i++;
        goto start; // Jump to the 'start' label
    }

    return 0;
}

Tokens

Tokens are the smallest individual units in a programming language. They are the building blocks that make up the source code. Tokens include keywords, identifiers, operators, constants, and punctuation symbols. For example, in the statement int x = 10;, the tokens are int, x, =, and 10.

Tokens are the smallest individual components of the source code, while statements are larger constructs made up of one or more tokens that represent a complete action or instruction in the program.


Keywords and Identifiers

Keywords are built-in reserved words in a C programming language. They are predefined words in C. There are 32 keywords in ANSI C.

autobreakcasechar
constcontinuedefaultdo
doubleelseenumextern
floatforgotoif
intlongregisterreturn
shortsignedsizeofstatic
structswitchtypedefunion
unsignedvoidvolatilewhile

Identifiers are user-defined words in a C programming language. They are defined by the programmers following the rules of an identifier. Examples of an identifier are a variable name, a constant name, a function name, an array name, a structure name, etc.

Rules of an identifier:

  • Identifiers in C can consist of letters(both uppercase and lowercase), digits and underscores. However, an identifier must begin with either underscore(_) or alphabets/letters.
    VALID : num, _num, num1, fir12st
    INVALID : 1num

  • Whitespaces (Blank Spaces) and hyphens(-) are not allowed in an identifier.
    VALID : first_name, firstname, firstName
    INVALID : first name, first-name, num-12

  • Keywords cannot be used as an identifier.
    VALID : intt, choice, ret, FLOAT
    INVALID : int, char, return, while

  • C is a case-sensitive language, so uppercase and lowercase letters are treated as distinct.
    VALID : num, NUM, nuM, nUm and Num are different in C.

  • An identifier must be unique.
    VALID :int num; and float num; is allowed in the different scopes.
    INVALID : int num; and float num; is not allowed in the same scope.

  • The C standards don't specify an exact maximum length for identifiers, but most compilers have practical limits. Generally, the first 31 characters of an identifier are significant in older C standards.


Variable

A variable is a named storage location in a memory. It is used to store and manipulate data within a program. Variables are crucial for storing values, such as numbers, text, or complex data structures, which can be used and modified as the program executes. A variable has the following key aspects:

  • Name: Each variable has a unique name that is used to identify it in the program.

  • Scope: Each variable has a scope or a range. The variable cannot be accessed outside of its scope.
    Local Scope : The variable can be accessed within a particular block only such as inside a function or a loop. Such variables are called local variables. Sometimes, it is desired to extend the life of a variable that is declared inside the function (local scope) to the global scope. We can achieve this by using a static keyword. Such variables are called static variables.
    Global Scope : The variable can be accessed from anywhere in the program. We must be careful with such variables because they can be modified from every part of our program. Such variables are called global variables.

  • Life: Each variable also has a life. The life of a variable means the period between a variable memory allocation(birth) and its deallocation(death).
    Local variables are allocated during the execution of the local block such as function and get deallocated after the completion of that function. There is no default initialization of local variables. It contains garbage values.
    Static variables and Global variables are allocated during the start of the program itself and get deallocated after the completion of the whole program. The default initialization of static and global variables is 0.


Constant

A constant is an immutable named storage location in a memory i.e. The value stored in a constant cannot be modified throughout the program during execution; hence the name, constant. A constant is defined using a const keyword.

  1. Integer Constants

    We have to explicitly initialize the value of an integer constant during it's declaration.

    const int num = 7;

  2. Floating Point Constants

    We have to explicitly initialize the value of a floating point constant during it's declaration.

    const float marks = 55.55;

  3. Character Constants

    We have to explicitly initialize the value of a character constant during it's declaration.

    const char ch = 'K';

  4. String Constants

    We have to explicitly initialize the value of a string constant during it's declaration.

    const char name[] = "C Programming is fun";

  5. Symbolic Constants

    These constants are not explicitly initialized because they are defined by the preprocessor directives.

    #define PI 3.14

    Here, PI is a symbolic constant with a value of 3.14. It is often termed as macros. The value of macro is replaced by the preprocessor directive during the first phase of compilation.

Did you find this article valuable?

Support Kushal Ghimire by becoming a sponsor. Any amount is appreciated!