Lesson 01: Introduction

Welcome to the first lesson in Programming in C. In this lesson, you will be introduced to the C programming language, guided through setting up your programming environment and writing your first C program.

Objectives

By the end of this lesson, you should be able to:

  • Understand the significance and applications of C.
  • Set up a C programming environment on your computer.
  • Write, compile, and run a simple C program.
  • Understand the basic syntax and structure of a C program.

Overview and history of C Programming

C is a powerful general-purpose programming language that has been widely used for decades in a variety of domains. C was developed by Dennis Ritchie at Bell Labs in the early 1970s. It was designed as a system implementation language for the Unix operating system, which itself was a significant milestone in the history of computing. C evolved from two previous languages, BCPL and B, and has influenced many other programming languages, including C++, C#, Java, and JavaScript. The American National Standards Institute (ANSI) adopted C as a standard in 1989 (ANSI C). The International Organization for Standardization (ISO) later adopted the standard, and it is now known as ISO C.

The design of C emphasized simplicity and power, reflecting the hacker ethos of creating efficient and effective solutions with minimal complexity. This made C an attractive tool for hackers who valued elegant, lean code. C’s ability to run on different hardware platforms without significant modifications contributed to the spread of Unix and the hacker culture associated with it. Hackers could transfer their skills and tools across different systems, enhancing their versatility and reach.

In the 1980s, Richard Stallman launched the GNU Project with the goal of creating a free Unix-like operating system. Much of the software developed for GNU was written in C, cementing C’s role in the free software movement. The GNU Compiler Collection (GCC) is one of the most prominent examples. In the early 1990s, Linus Torvalds created the Linux kernel, which was also written in C. Linux, combined with the GNU tools, formed a complete operating system (GNU/Linux) that became a cornerstone of free software and hacker communities.

For many hackers and programmers, learning C was a rite of passage. It provided deep insights into how software interacts with hardware, memory management, and system-level programming. Mastery of C often distinguished skilled programmers within the hacker community.

Often referred to as K&R, the book "The C Programming Language" by Kernighan and Ritchie became the definitive guide to C and a staple in the education of many programmers and hackers. Its clear explanations and practical examples made it an essential resource.

The hacker culture is characterized by the free exchange of knowledge and code. C programs, libraries, and tools were frequently shared, modified, and improved by the community, embodying the collaborative spirit of hacking. Many innovations in software development, including early internet protocols, influential software projects, and security tools, were developed by hackers proficient in C. These contributions have had lasting impacts on the field of computing.

Thus, the development of the C programming language is deeply connected to the history of hacking culture. C’s creation and evolution paralleled the growth of a community that valued openness, efficiency, and collaboration, all of which are core tenets of hacking culture.

Applications of C Programming

As C programs are highly portable they can run on different types of hardware with little or no modification. C provides low-level access to memory and minimal runtime support, allowing for high-performance applications. Understanding C provides a solid foundation for learning other programming languages, particularly those that are syntactically similar (like C++ and Java). Other high-level languages such as (C)Python are also written in C.

Thus, C is used for various applications. Many operating systems, including Unix and GNU/Linux, are written in C. C is commonly used in embedded systems due to its efficiency and control over hardware. Many compilers and interpreters for other programming languages are written in C. Applications that require high performance and low-level hardware interaction, such as game engines and database management systems, often use C.

Setting Up the Environment

To write and compile C programs, you need to set up a development environment that includes a compiler and optionally an integrated development environment (IDE). This course do not require an IDE to be used.

Installing a C Compiler

A compiler translates C code into machine code that your computer can execute. Here’s how to install the GCC (GNU Compiler Collection) on different operating systems:

Linux (preferred option)

  1. Open your terminal
  2. Install GCC using your package manager. For example, on Debian-based systems (like Ubuntu), run:
    sudo apt-get update 
    sudo apt-get install gcc 
    

macOS

  1. Open your terminal with Spotlight by hitting Command + Spacebar and typing "Terminal" and hitting return
  2. Enter the following to begin installing Command Line Tools:
    xcode-select --install 
    

  3. Agree to install the Command Line Tools package, when that is complete you can now install Homebrew package manager onto the Mac with the following command string:
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 
    

  4. After Homebrew has finished installing, you can install GCC with the following command:
    brew install gcc 
    

Windows

  1. Download tdm64-gcc-<version>.exe from https://jmeubank.github.io/tdm-gcc/download/ which includes the 64+32-bit MinGW-w64 edition of GCC.
  2. Execute the downloaded installer and choose the option to "Create" a new TDM-GCC installation. You would probably want the MinGW-w64 edition as well. Apart from that, the default settings should suffice.

Writing Your First C Program

With your environment set up, you’re ready to write your first C program. Follow these steps:

  1. Open a text editor of your choice and create a file named hello.c
  2. Copy or type the following code:
    /* This tells the compiler to use predefined functions from the library stdio. 
    * In this program we use the stdio library to include the function printf() 
    * which is used printing a formatted text to the standard output (STDOUT). 
    * 
    * read more: https://www.geeksforgeeks.org/printf-in-c/ 
    */ 
    #include <stdio.h> 
     
    /* the main function of a C program is the first function to be called when the 
    * program is being executed. depending on your use case, you might use an 
    * alternative implementation of the main function to include arguments: 
    * int main(int argc, char** argv) 
    * 
    * read more: https://www.geeksforgeeks.org/main-function-in-c/ 
    */ 
    int main() 
    { 
        printf("Hello, World!\n");  /* print "Hello, World!" and a new line */ 
        return 0;                   /* return 0 (successful ending) */ 
    } 
    

  3. Save the file!
  4. Now, the code can be compiled into an executable using the installed compiler
  5. Open your terminal (or Command Prompt/PowerShell on Windows)
  6. Navigate to the directory where your hello.c file is saved
  7. Compile the program by runnig: gcc hello.c -o hello
  8. Run the compiled program:
    • On Linux/macOS: ./hello
    • On Windows: hello.exe
  9. If everything worked, the terminal should say "Hello, World!"

Basic Syntax and Structure

Comments

Comments are used to explain the code and are ignored by the compiler. In the example above I used multi-line comments for all cases, even when the comments could fit on one line. The reason for this is that even if you remove all line breaks the code would still compile. My personal recommendation is to always use multi-line comments.

  • Single-line comment: // this is a single-line comment
  • Multi-line comment: /* This is a multi-line comment */

The big difference between single- and multi-line comments is that multi-line comments are interpreted as comments from the first instance of /* until the first instance of */

Why use comments?

Ensuring accurate and reflective comments is crucial for code clarity and functionality. Misleading comments can lead to confusion and potential compilation errors. Whenever code changes are made, it’s essential to update corresponding comments to maintain synchronization and accuracy. Comments should not be nested but rather self-contained and independent. It’s acceptable to split comments across multiple lines for readability and detailed explanations, which aids in maintaining clarity and organization.

Comments can be strategically placed throughout a program to provide explanations, descriptions, or documentation where needed. There’s no limit to the number of comments within a program, allowing freedom to enhance readability and maintainability, especially in longer codebases. They summarize algorithms, clarify variable purposes, and elucidate unclear segments, thus facilitating understanding of the code’s logic and structure.

For developers, comments are invaluable when anticipating others to read and collaborate on the codebase. They provide concise descriptions that simplify comprehension and aid in project collaboration. Additionally, comments serve as reminders for the original author, helping to quickly recall information, especially after extended periods or when reusing code in different projects.

Functions

Functions are blocks of code that perform specific tasks. Functions can accept arguments and return values. However, this is not a requirement for a function in C.

Function Declaration:

Specifies the function name, its parameters and return value. They are often specified in a header-file or at the top of the program before any program logic. The function declaration tells the compiler that there is a function with the given name defined somewhere else in the program. Example:

int main(int argc, char** argv); 

pic-0.png

In this example the return type is int, the name of the function is main and its parameters are argc and argv. argc accepts an int argument, while argv accepts a pointer to a pointer (**) of char. More on data types and pointers later.

Function Definition:

Includes the function body that contains the program logic and statements to be executed. Example:

int main(int argc, char** argv) 
{ 
    printf("I got %d arguments\n", argc - 1); 
    return 0; 
} 

In this definition of the main function, the argument for the parameter argc is used for printing the number of command line arguments received by the program. Here the arguments received by the function, argc and argv, differ from the command line arguments received by the program upon execution. Lets say that the program is called numberOfArguments and it’s executed like so:

./numberOfArguments one two three four 

The program would print I got 4 arguments. Still, the main function only receives two arguments:

  1. argc, the number of command line arguments (5 in this case, including "numberOfArguments")
  2. argv, a pointer to pointer of a character (these pointers could be used for retrieving the command line arguments)
Function Call:

A function call is a statement that instructs the program to execute the function being called. We use the function name and parameters when creating a function call. If the function accepts arguments these are included in reference to the function parameters. Example:

printf("I got %d arguments\n", argc - 1); 

In the example above the function printf is being called using two arguments. First a string is used for specifying a printable format. In this string a placeholder (%d) is used for printing an integer. The second argument is an integer specified by the subtraction of 1 from the variable argc.

Statements and Blocks

Statements are individual instructions, such as function calls, and blocks are groups of statements enclosed in {}, such as functions. Statements are ended with a semicolon ;.

Whitespaces

Whitespaces (spaces, tabs, newlines) are ignored by the compiler but helps make the code more readable. Example:

int main() 
{ 
    /* a comment */ 
    printf("Welcome to C programming!\n"); 
    return 0; 
} 

This code block could be written without whitespaces, like so:

int main(){/* a comment */printf("Welcome to C programming!\n");return 0;} 

However, the whitespaces makes the code much more readable.

It’s importent to note that various development projects use their own coding style, that’s required to follow when contributing code. Here are some examples:

Exercises

  1. Set Up Your Environment: Install a C compiler and optionally an IDE of your choice.
  2. Write and Run Your First Program: Create and execute the "Hello, World!" program.
  3. Modify the Program: Change the message to "Welcome to C programming, [NAME]!" and run it again. The program should print the name based on a command line argument.

    Tips:

    • Strings (text) are printed using the placeholder %s.
    • By using the parameters int argc, char** argv, argv could be used to retrieve the nth command line argument: argv[n]

    Execution of a fully working program should look like this:

    ./hello Sasha 
    Welcome to C programming, Sasha! 
    

Next Lesson

In the next lesson, we will delve into Datatypes and Variables, where we will explore the different types of data C can handle and how to declare and use variables.

Next Lesson