Goal of this Course

The goal of this course is to enable all participants to learn proper software engineering. Being a good software engineer takes time, will to improve yourself and commitment.


wikimedia

Table of Contents

Learn2code Part I

Literature

free c-books

basics of this course

Benjamin Wilking ©
Learn2code Part I

Exercises@Home & Exam

Homework

  • Homework is voluntary but strongly recommended.
  • You are welcome to ask questions, I'm glad to help.

Exam

  • During the last 3 weeks of the course.
  • In teams of up to 2 people.
  • Delivery in Git.
Benjamin Wilking ©
Learn2code Part I

Some Linux Basics

Benjamin Wilking ©
Learn2code Part I

The Shell

Simply put, the shell is a program that takes commands from the keyboard and gives them to the operating system to perform. [...] (linuxcommand.org)

Benjamin Wilking ©
Learn2code Part I

bash vs. zsh

The most common shell is the bash (Bourne Again SHell). Code snippets in this course are given for bash.

The zsh (Z shell) is getting more and more popular and is already the standard on some systems (e.g. Apple).

If you open a terminal with a zsh, you can always type in bash and you will get a bash shell.

Benjamin Wilking ©
Learn2code Part I

Basic Bash Commands

  • go to home cd ~ or just cd
  • go to last folder cd -
  • show current directory pwd
  • list content of current folder ls -la (man ls)
  • create a new file touch my_new_file.ext
  • create a new directory mkdir my_new_dir
  • go to directory
    • absolute path cd /home/<username>/my_new_dir
    • relative path cd ./my_new_dir
    • one level up cd ..
  • open file in editor nano my_new_file.ext (or any other editor)
  • rename (move) a file mv my_new_file.ext my_new_file.new_ext
  • remove file rm my_new_file.new_ext
  • remove directory rm -rf my_new_dir (⚠️ very dangerous, always double check)
  • put some text to a file echo "some strange text" >> my_textfile.txt
  • find text in file grep -rnw '.' -e 'strange'
  • ☝️ "double-tab" completes your input and gives you your possibilities
  • ⬆️ goes through the command history
Benjamin Wilking ©
Learn2code Part I

Task: Linux Basics

  1. Go to your home folder.
  2. Create a new file in a new folder.
  3. "echo" some text to the file
  4. open the file with an editor and add more lines
  5. find a certain string in the file with grep
  6. create a second empty file
  7. delete the second file
  8. delete the created folder

(in between, always check the current status with ls)

Benjamin Wilking ©
Learn2code Part I

The Language C

C [...] is a general-purpose computer programming language. It was created in the 1970s by Dennis Ritchie, and remains very widely used and influential. [...]. C is commonly used on computer architectures that range from the largest supercomputers to the smallest microcontrollers and embedded systems. (wikipedia)


If programming languages were vehicles

Benjamin Wilking ©
Learn2code Part I

The basics Example

Create a new file basics.c with the following content

int main()
{
  return 0;
}

compile it

gcc basics.c # using the gnu compiler
clang basics.c # using the clang compiler

the result is a binary called a.out.
You can run the program with ./a.out

Benjamin Wilking ©
Learn2code Part I

If you want to give the binary a better name use the "-o" option

gcc basics.c -o basics 

You can check all possible options with

man gcc # or 'man clang'

Finally, you can run the binary with

./basics

☝️ you can check the return value with: ./basics; echo $?

Benjamin Wilking ©
Learn2code Part I

Git

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. (Git)

Benjamin Wilking ©
Learn2code Part I

What is Version Control

In software engineering, version control (also known as revision control, source control, or source code management) is a class of systems responsible for managing changes to computer programs, documents, large web sites, or other collections of information. (wikipedia)

Benjamin Wilking ©
Learn2code Part I

Version Control Example Graph

Benjamin Wilking ©
Learn2code Part I

TensorFlow - Most Famous Project on GitHub

TensorFlow is an end-to-end open source platform for machine learning. (TensorFlow@GitHub)


Example Blame

Benjamin Wilking ©
Learn2code Part I

Working on a Local Repository

mkdir test_repo && cd test_repo
git init # initialize the repository
git status # check status of repository
echo "my first line" > first_file.txt # write something to a new file 
# -> check status
git add first_file.txt # add the file to version control 
# -> check status
git commit -m"initial commit (short msg)" -m"description (long msg)"
# commit the change to the repo 
# -> check status
gitk # opens the git native commit graph
git gui # opens the git native user interface
git log # check your changes on the command line
git log --graph # show the commit graph on command line
Benjamin Wilking ©
Learn2code Part I

Task: Branching in Git

  1. create a branch with git branch my_new_feature
  2. check the available branches with git branch
  3. switch to you new branch with git checkout my_new_feature
  4. add a new file and edit the one you already have
  5. commit your changes
  6. switch back to your main/master branch
  7. merge your changes to your main/master with git merge my_new_feature
  8. delete your feature branch with git branch -D my_new_feature
  9. check your commit graph

☝️ always remember to check your work with git status

Benjamin Wilking ©
Learn2code Part I

Working on a Remote Repository

Benjamin Wilking ©
Learn2code Part I

Prerequisites

  1. On GitHub create a new repository from the learn2code template

  2. Add an SSH key for your machine

    • Print your public key to console: cat .ssh/id_rsa.pub
    • On GitHub: profilesettingsSSH and GPG keysNew SSH key
      • paste and add your public key with a descriptive name
Benjamin Wilking ©
Learn2code Part I

Playing around

Go to the new repository you created in the last step and get the URL: CODE ➡️ local ➡️ SSH

git clone <InsertYourRepoURL> # get the repo
cd <YourRepoName> # go into the repo folder
echo "some text" > <your file name> #write text to file
# add and commit your changes
git push # bring local changes to the remote repo
Benjamin Wilking ©
Learn2code Part I

Some Basics for Git

  • do not add binary (large) files
  • always write a descriptive message (short + long)
  • use .gitignore to keep your workspace clear
  • get familiar with the command line
  • learn the best practices
Benjamin Wilking ©
Learn2code Part I

Common Environment

Benjamin Wilking ©
Learn2code Part I

Why Should I Use It?

  • Maybe you don't have a linux PC
  • We all have the same system (compiler etc.)
    • If it works on your machine, it works on my machine
  • Necessary tools and configs are already installed
Benjamin Wilking ©
Learn2code Part I

Benjamin Wilking ©
Learn2code Part I

gitpod

Gitpod is an open-source Kubernetes application for ready-to-code cloud development environments that spins up fresh, automated dev environments for each task, in the cloud, in seconds. (gitpod@github)

You can use this repo and the corresponding gitpod

Contribute with Gitpod

Benjamin Wilking ©
Learn2code Part I

GitHub Codespaces

A codespace is a development environment that's hosted in the cloud. You can customize your project for GitHub Codespaces [...], which creates a repeatable codespace configuration [...]. (github)

You can use this repo and the corresponding codespace

Open in GitHub Codespaces

Benjamin Wilking ©
Learn2code Part I

Basics in C #1

Benjamin Wilking ©
Learn2code Part I

Using the C Standard Library

The C standard library or libc is the standard library for the C programming language, as specified in the ISO C standard. [...].

The C standard library provides macros, type definitions and functions [...].
(wikipedia)

Benjamin Wilking ©
Learn2code Part I
#include <stdio.h>  //specify where to look for the functions you need
int main()
{
  /* print something to the command line
  make sure to end with a new line "\n"
  you can find more "control-characters" 
  on e.g. https://en.wikipedia.org/wiki/Control_character
  BTW: this is a multi-line comment */
  printf("Hello World!\n");

  return 0;
}

printf

Benjamin Wilking ©
Learn2code Part I

Macros

#include <stdio.h>  //specify where to look for the functions you need

//define a macro, from now on we can use "new_line" instead of "\n"
#define new_line "\n" 

int main()
{
  // append the macro to the string
  printf("Hello World!"new_line);

  return 0;
}

define

Benjamin Wilking ©
Learn2code Part I

Variables & Data Types

As a programmer you want to work with variables to remember a certain value.
In C, there are three kinds of basic data types for variables

  • int - integer (whole number) values
  • float - floating point values
  • char - single character values (such as “m” or “Z”)
Benjamin Wilking ©
Learn2code Part I

Working with Variables

Defining and using a variable in the code is quite easy:

int main()
{
  int x; // defines an integer variable named x
  float y = 1.0; // defines a variable and assigns a value

  x = 5; // initialize x before first usage
  x = x+x; // re-assign a value to x
  return 0;
}
Benjamin Wilking ©
Learn2code Part I

Printing Variables to the Console

Using printf, the output depends on the datatype!

  • int (integer values) uses %d
  • float (floating point values) uses %f
  • char (single character values) uses %c
  • character strings (arrays of characters, discussed later) use %s
printf("my int %d; my float %.2f; my char %c\n", x, y, c)
Benjamin Wilking ©
Learn2code Part I

Operators

  • + − addition
  • − subtraction
  • / − division
  • − multiplication
  • % − modulo

Operator precedence is comparable to mathematics.

There are many more, you should go through them at least once!

Benjamin Wilking ©
Learn2code Part I

Some operators make life easier!

x = x + 1; <-> ++x; 
x = x + y; <-> x+=y;

⚠️ NEVER rely on operator precedence

int a = 1;
int b = a++; // stores 1+a (which is 2) to a
             // returns the value of a (which is 1)
             // After this line, b == 1 and a == 2
a = 1;
int c = ++a; // stores 1+a (which is 2) to a
             // returns 1+a (which is 2)
             // after this line, c == 2 and a == 2

(example from here)

Benjamin Wilking ©
Learn2code Part I

Structures & Arrays

Benjamin Wilking ©
Learn2code Part I

Structures

int main()
{
  // declare a structure and name it "my_struct"
  struct my_struct 
  {
    int a,b,c;
    float d,e,f;
  }ms1; // instantly instantiate a structure of this type with name ms1
  // instantiate a structure without initialization -> be careful
  struct my_struct ms2;
  // instantiate a structure with initialization
  struct my_struct ms3 = {.a=5, .b=6, .c=7, .d=0.1, .e=0.2, .f=0.3};
  // access elements of a structure 
  int k = ms3.a + ms3.b + ms3.c;
  return 0;
}
Benjamin Wilking ©
Learn2code Part I
// globally defined structure (outside of main)
// works equivalent to define a structure inside of main
struct outer_struct 
{
  int a,b,c;
  float d,e,f;
};

// declare a new type of structure
// typedef can be used to define any kind of new type
// https://en.cppreference.com/w/c/language/typedef
typedef struct 
{
  int a,b,c;
  float d,e,f;
} outer_td_struct;

int main()
{
  //locally instantiated structure "or" with direct initialization 
  struct outer_struct or = {.a=5, .b=6, .c=7, .d=0.1, .e=0.2, .f=0.3};

  //using the new type of structure to instantiate structure "otd"
  outer_td_struct otd = {.a=5, .b=6, .c=7, .d=0.1, .e=0.2, .f=0.3};

  return 0;
}
Benjamin Wilking ©
Learn2code Part I

Arrays

int main()
{
  int a[5]; // declare an array without initialization -> be careful
  int b[5] = {0}; // initialize all values with zeros
  int c[5] = {22, 33, 44, 55, 66}; // initialize all values explicitly
  int d[] = {22, 33, 44, 55, 66};  // you don't need to specify the size
  int e[5];
  e[0] = 10; // !!! array indices always start at 0 ....
  e[1] = 3;
  e[2] = 13;
  e[3] = 22;
  e[4] = 77; // ... and end with n-1

  return 0;
}
Benjamin Wilking ©
Learn2code Part I

Pointers

Benjamin Wilking ©
Learn2code Part I

Using Pointers

int i, j;
int *p;  // define pointer to integer. p holds a random unknown address now
// trying to use *p most probably creates a seg fault
int *pi = NULL;  // now pointer is initialized. Still a segfault, but we can check it
printf("uninitialized: p points to: %p\n", p);  // %p is "pointer address"
p = &i;                                         // assign the address of i to p
printf("initialized p, uninitialized i: value *p=%d, p points to %p\n", *p, p);
*p = 5;  // assign value to the memory of the pointer
printf("initialized p, initialized i: value *p=%d, p points to %p\n", *p, p);
j = i;  // copy the value from i to j
printf("i=%d, j=%d, value *p=%d, p points to %p\n", i, j, *p, p);

struct my_struct
{
    int a;
    float b;
} my1 = {.a = 2, .b = 3.3f};
struct my_struct *p_my2 = &my1;
// accessing elements of pointer-to-struct is done by "->" instead of "."
printf("Struct value a=%i from instance; struct value b=%.1f from pointer!\n", my1.a, p_my2->b);
Benjamin Wilking ©
Learn2code Part I

Size of Pointers

// sizeof returns the size of a datatype in bytes
// lets test the size of some basic datatypes
printf("size of char: %lu\n", sizeof(char));
printf("size of int: %lu\n", sizeof(int));
printf("size of float: %lu\n", sizeof(float));
printf("size of double: %lu\n", sizeof(double));
printf("size of long: %lu\n", sizeof(long));

printf("size of char*: %lu\n", sizeof(char*));
printf("size of int*: %lu\n", sizeof(int*));
printf("size of float*: %lu\n", sizeof(float*));
printf("size of double*: %lu\n", sizeof(double*));
printf("size of long*: %lu\n", sizeof(long*));
Benjamin Wilking ©
Learn2code Part I

What is Compiling?

Benjamin Wilking ©
Learn2code Part I

Preprocessor - Compiler - Linker

Preprocessor

gcc -E basics_in_c_macro.c
# or
clang -E basics_in_c_macro.c

Can you figure out what the preprocessor does?

Benjamin Wilking ©
Learn2code Part I

Compiler

clang -c basics_in_c_macro.c
nano basics_in_c_macro.o # naive approach to show content of object file
objdump -D basics_in_c_macro.o # use linux tools to inspect the file

Task

Figure out the options in the following command. What are they doing?

clang -Wall -Wextra -Werror -pedantic -O0 basics_in_c_macro.c
Benjamin Wilking ©
Learn2code Part I

Example Implicit Conversion

Additional compiler flags can help you in finding bugs very early.
A typical example is the implicit conversion

int b = 2;
float a = 5.0F;
a = 5.0 / b;
printf("float a = %.3f\n", a);  // seems to work correctly -> a = 2.500
a = 5 / b;
printf("float a = %.3f\n", a);  // definitely wrong output -> a = 2.000

You could find this problem with the gcc flag -Wconversion

Benjamin Wilking ©
Learn2code Part I

Linker

We did not call the linker!
Well, let's check if we linked something

On Linux

ldd a.out

On Mac

otool -L a.out
Benjamin Wilking ©
Learn2code Part I

Compiler vs. Interpreter

compiler vs interpreter

C

#include <stdio.h>
int main()
{
    printf("Hello World!\n");

    return 0;
}
clang basics_in_c.c && ./a.out
Benjamin Wilking ©
Learn2code Part I

Python

print("Hello World!")
python3 basics_in_c_python.py

What are the advantages of the interpreter language?
What are the downsides?

Benjamin Wilking ©
Learn2code Part I

CMake

CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files [...]. (CMake)

Book recommendation: Professional CMake

Benjamin Wilking ©
Learn2code Part I

CMake Toolchain Workflow

Benjamin Wilking ©
Learn2code Part I

Write a CMake Config

CMake config is always a file named CMakeLists.txt

# define the minimum cmake version
cmake_minimum_required(VERSION 3.20)

# define the project name
project(cmake_example VERSION 1.0 LANGUAGES C)

# define the c standard version
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)

# add some compile options
add_compile_options(-Wall -Wextra -pedantic -O0)

# add an executable and assign files to it
add_executable(cmake_example_exec cmake.c)
Benjamin Wilking ©
Learn2code Part I

Running CMake

cd <folder-with-CMakeLists.txt>
cmake . # run cmake
make # build your project
./cmake_example # run your binary

Result: your workspace gets polluted 😒

Benjamin Wilking ©
Learn2code Part I

Define sources and build folder

cmake -S . -B build
☝ Please delete all generated files from your workspace first
Still, there are some things undefined. Add:
-G "Unix Makefiles" 
-D CMAKE_C_COMPILER=gcc 
-D CMAKE_CXX_COMPILER=g++ 

(you could also use e.g. the llvm toolchain with clang-16 and clang-cpp-16)

Figure out what these options are doing with:

cmake --help
(Learn more about generators, make, ninja)
Benjamin Wilking ©
Learn2code Part I

Still, calling CMake seems to be tedious 😓
Let's create a small script for that.
Create a file called run_cmake.sh

#!/bin/bash
cmake -S . -B build #add all your options
Benjamin Wilking ©
Learn2code Part I

CMake Misc

  1. You probably recognized, that you have to go to the build folder before calling make 😉
  2. Can you run your script run_cmake.sh? Probably not! Try chmod +x run_cmake.sh! - What does this?
Benjamin Wilking ©
Learn2code Part I

Debugging

In computer programming and software development, debugging is the process of finding and resolving bugs (defects or problems that prevent correct operation) within computer programs, software, or systems. (wikipedia)

Benjamin Wilking ©
Learn2code Part I

Debugging-Prerequisites

  • you have to tell the compiler to create debug symbols

    • extend CMake build with:
    cmake -S . -B build -DCMAKE_BUILD_TYPE=DEBUG
    
  • either use gdb or lldb

Benjamin Wilking ©
Learn2code Part I

Debug with lldb

(⚠️ unfortunately not working on codespace / gitpod)

lldb debugging_example_exec # this is the name of your binary defined in CMakeLists.txt
(lldb) breakpoint set --file debugging.c  --line 12 # this is the name of your source file
(lldb) process launch
(lldb) help # to get the possible commands
(lldb) v # shows all variables
(lldb) v val1 # shows only variable val1
(lldb) s # step to next line or step into current function
(lldb) c # continue to next breakpoint or end
(lldb) exit # leave lldb
Benjamin Wilking ©
Learn2code Part I

Debug With gdb

gdb debugging_example_exec # this is the name of your binary defined in CMakeLists.txt
(gdb) break debugging.c:12 # this is the name of your source file
(gdb) run
(gdb) help # to get the possible commands
(gdb) info locals # shows all variables
(gdb) p val1 # shows only variable val1
(gdb) s # step to next line or step into current function
(gdb) next # continue to next breakpoint or end
(gdb) q # leave gdb
Benjamin Wilking ©
Learn2code Part I

Visual Studio Code

Until now, we did everything on the command line.
It is time to get a bit lazy 😏
(You have to have the CMake Tools Extension installed)

Benjamin Wilking ©
Learn2code Part I

VS Code - Loading the Project

  • right click CMakeLists.txtConfigure All Projects
  • If you are asked for to select a kit → select one for linux
Benjamin Wilking ©
Learn2code Part I

VS Code - Build, Run & Debug

After configuring the project, you can build, run & debug your project using the extension buttons on the bottom of the window.

There, you can also change:

  • build toolkit
  • Debug/Release configuration
  • build target
    ...

❗ If you cant see the CMake status bar, add this line to your .vscode/settings.json file

"cmake.options.statusBarVisibility": "compact",
Benjamin Wilking ©
Learn2code Part I

VS Code - Git

There are also several Git Extensions.
A very good one is Git Lense.
Even if is absolutely mandatory to know the git command line, VS Code gives you some comfort:

  • Check the git symbol on the left of VS Code
  • Check the additional right click actions for files
  • ...
Benjamin Wilking ©
Learn2code Part I

Code Formatting with VS Code

Using a common coding format eases collaboration on code a lot.
Common coding format contains rules about: braces, brackets, number of spaces (tab usage), spaces between operators, and many more.

VS Code provides an easy way to format your files automatically.

  • install clang-tidy
  • install VS Code extension xaver.clang-format
  • copy the .clang-format config file to your main folder
  • open a file and press Ctrl + ⇧ + P (⌘ + ⇧ + P)
  • search for format document → click to execute
Benjamin Wilking ©
Learn2code Part I

User Input in C

  • Reading user input is as easy as printing something.
  • Similar to printf we use scanf to read in values.
  • The type of data is important, e.g. %d for integer values
// read in an integer value from the console
scanf("%d", &val1) ;

☝️ The & sign is very important. We learned that in the chapter pointers

Benjamin Wilking ©
Learn2code Part I

Basics in C #2

Benjamin Wilking ©
Learn2code Part I

Branching & Looping

Benjamin Wilking ©
Learn2code Part I

if

  int b;
  printf("Enter a value:");
  scanf("%d",&b);
  if(b < 0)
  {
    printf("The value is negative\n");
  }
  else if(b==0)
  {
    printf("The value is zero\n");
  }
  else
  {
    printf("The value is positive\n");
  }

Read more about comparison operators

Benjamin Wilking ©
Learn2code Part I

switch case

int a = 2;
switch (a)
{
    case 1:
        printf("a is one\n");
        break;
    case 2:
        printf("a is two\n");
        break;
    case 3:
        printf("a is three\n");
        break;
    default:
        printf("a is something else\n");
        break;
}
Benjamin Wilking ©
Learn2code Part I

while

int a = 0, b = 10;
while (a < b)
{
  printf("%d\n", a);
  ++a;
}
int a = 0, b = 10;
do
{
  printf("%d\n", a);
  ++a;
}while (a < b);
Benjamin Wilking ©
Learn2code Part I

for

The for loop in C is simply a shorthand way of expressing a while statement (The Basics of C Programming)

int a = 0, b = 10;
while (a < b)
{
  printf("%d\n", a);
  ++a;
}
int a, b;
for (a = 0, b = 10; a < b; ++a)
{
  printf("%d\n", a);
}
Benjamin Wilking ©
Learn2code Part I

Functions

So far, we wrote spaghetti-code 🍝
We can change this by defining a function

return_value my_function_name(<datatype> input_1, <datatype> input_2)
{
  <do something>
  return <a value>;
}

Put this IN FRONT of your main and you can use the function in the code!

Benjamin Wilking ©
Learn2code Part I

Create a Prototype

The overview is not very good having all the functions in front of the main.
You can create a prototype only instead:

return_value my_function_name(<datatype> input_1, <datatype> input_2);

Now, you can define the function AFTER the main

int main(void) {return 0;}

return_value my_function_name(<datatype> input_1, <datatype> input_2)
{
  <do something>
  return <a value>;
}
Benjamin Wilking ©
Learn2code Part I

Create Files for Prototype and Definition

Even with the prototype, the overview is not perfect. Putting code in separate files would help!

  1. Create a header file for the prototype (e.g. include/functions.h). Always use include guards
  2. Create a source file for the definition (e.g. src/functions.c)
  3. Include the header in your main file
  4. Tell the compiler where to find everything (CMakeLists.txt ➡️ target_include_directories)
Benjamin Wilking ©
Learn2code Part I

Include Guards

/*
    always put an "include guard" on top.
    good practice is to use the uppercase file name + a random string.
    In big projects you never know if somebody else named the file and the
    include guard the same.
    For random Strings use e.g. https://www.random.org/strings/
*/
#ifndef FUNCTIONS_H_18RqkXbbAj
#define FUNCTIONS_H_18RqkXbbAj

// prototypes and definitions go here!

#endif /* FUNCTIONS_H_18RqkXbbAj */

random string online
or
VS Code extension insert-random-text

Benjamin Wilking ©
Learn2code Part I

Future Project Structure

From now on, we will stick to the following folder structure

  • <project-name>
    • include ( ➡️ contains all header files)
    • src ( ➡️ contains all source files)
    • test ( ➡️ contains test files)
    • doc ( ➡️ contains relevant files for documentation)
    • CMakeLists.txt
    • readme.md
    • ...
Benjamin Wilking ©
Learn2code Part I

Pointers as Function Arguments

Benjamin Wilking ©
Learn2code Part I

Libraries

So, we learned how to extract code into extra files 🎇.
It could be even better.
How about creating an own library - like the C standard library we use all the time?

Benjamin Wilking ©
Learn2code Part I

Types of Libraries


source                                           source

Benjamin Wilking ©
Learn2code Part I

How to Create a Library

On Linux and using CMake, creating a library is dead simple ✨

# add a library
add_library(<library_name> <STATIC | SHARED> <source_files>)
# add the includes to the library
target_include_directories(<library_name> PUBLIC include)

Now, you can use the new library for your executable

# add an executable and assign files to it
add_executable(<exec_name> src/main.c)
# add the include directories
target_include_directories(<exec_name> PUBLIC include)
# link your libraries
target_link_libraries(<exec_name> PRIVATE <library_name>)

To be honest: using (3rd party) libraries can be extremely tedious 😢

Benjamin Wilking ©
Learn2code Part I

Task: Create Two Libraries and Consume Them

  1. Create a static library which contains a function to add two integers
  2. Create a shared library which gives you a nice Batman print
  3. Create a main which consumes (links and uses) both libraries
  4. Figure out what the Linux tool ldd does
  5. Check your compiled main with ldd, what do you see (and what not)?
Benjamin Wilking ©
Learn2code Part I

Const Correctness

Benjamin Wilking ©
Learn2code Part I

What is const

const type qualifier

/* declare a const value variable */
const int value_c = 33; // const value variable
value_c = 0; // assign a new value -> ERROR
Benjamin Wilking ©
Learn2code Part I

Different Types of const Pointers

/* declare a normal pointer */
int* ptr = &value_a;
ptr = &value_b; // assign a new memory address
*ptr = 33; // assign a new value

/* declare a const value pointer */
int const * const_s_ptr = &value_a; // const value pointer
const_s_ptr = &value_b; // assign a new memory address
*const_s_ptr = 44; // assign a new value -> ERROR

/* declare a const address pointer */
int * const s_const_ptr = &value_a; // const address pointer
s_const_ptr = &value_b; // assign a new memory address -> ERROR
*s_const_ptr = 55; // assign a new value

/* declare a const value and const address pointer*/
int const * const const_s_const_ptr = &value_a; // const value const address pointer
const_s_const_ptr = &value_b; // assign a new memory address -> ERROR
*const_s_const_ptr = 44; // assign a new value -> ERROR
Benjamin Wilking ©
Learn2code Part I

const Correctness in Functions

int* my_const_correct_function(int * mutable_ptr, int const * const immutable_ptr)
{
  int * inside_ptr; 
  int const * const inside_csc_ptr = immutable_ptr;

  inside_ptr = mutable_ptr; // fine
  ++*inside_ptr;  // fine
  ++*mutable_ptr; // fine
  
  //inside_ptr = immutable_ptr; // BAD, warning: assignment discards ‘const’ qualifier 
  //++*immutable_ptr; // ERROR, can not change the pointer value or address

  return inside_ptr; // fine
  //return inside_csc_ptr; // BAD, return discards ‘const’ qualifier
}
int* return_ptr = my_const_correct_function(ptr, s_const_ptr);
Benjamin Wilking ©
Learn2code Part I

Continuous Integration, Delivery & Deployment

Benjamin Wilking ©
Learn2code Part I

Continuous Integration

In software engineering, continuous integration (CI) is the practice of merging all developers' working copies to a shared mainline several times a day. (wikipedia)

Benjamin Wilking ©
Learn2code Part I

Continuous Delivery

Continuous delivery (CD) is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time and, when releasing the software, without doing so manually. (wikipedia)

Benjamin Wilking ©
Learn2code Part I

Continuous Deployment

Continuous deployment (CD) is a software engineering approach in which software functionalities are delivered frequently and through automated deployments. (wikipedia)

Benjamin Wilking ©
Learn2code Part I

CI/CD Tools

Benjamin Wilking ©
Learn2code Part I

Github Actions

Github Actions allow you to continuously integrate, deliver and even deploy your software.
For now, we want to use Github Actions to build and test our software continuously.


☝️ There is way more we could do, but that's the absolute minimum

Benjamin Wilking ©
Learn2code Part I

Create New Action (Pipeline)

Benjamin Wilking ©
Learn2code Part I

Add a Workflow

Benjamin Wilking ©
Learn2code Part I

Add CMake Workflow

Benjamin Wilking ©
Learn2code Part I

Specify Your Build Commands

You will get a first proposal for your workflow file.
E.g. .github/workflows/cmake.yml
In this file you need to make sure, that

  1. gtest is installed (if you need it)
  2. all your build steps are executed
  3. all your paths are correct
Benjamin Wilking ©