[SPCA] Restructure, intro to C continued

This commit is contained in:
2026-01-05 16:48:36 +01:00
parent 4a02e20218
commit 433111833c
16 changed files with 154 additions and 9 deletions

View File

@@ -13,4 +13,5 @@ int main( int argc, char *argv[] ) {
printf( "Arg %d: %s\n", i, argv[ i ] ); // Outputs the i-th argument from CLI
get_user_input_int( "Select a number" ); // Function calls as in any other language
return 0; // Return a POSIX exit code
}

View File

@@ -1,9 +1,11 @@
#include "01_func.h"
#include <stdio.h>
int get_user_input_int( char prompt[] ) {
int input_data;
printf( "%s", prompt ); // Always wrap strings like this for printf
scanf( "%d", &input_data ); // Get user input from CLI
printf( "%s", prompt ); // Always wrap strings like this for printf
scanf( "%d", &input_data ); // Get user input from CLI
int input_data_copy = input_data; // Value copied
// If statements just like any other language
if ( input_data )
@@ -11,6 +13,7 @@ int get_user_input_int( char prompt[] ) {
else
printf( "Input is zero" );
// Switch statements just like in any other language
switch ( input_data ) {
case 5:
printf( "You win!" );
@@ -21,17 +24,20 @@ int get_user_input_int( char prompt[] ) {
printf( "No win" ); // Case for any not covered input
}
int input_data_copy = input_data;
while ( input_data > 1 ) {
input_data -= 1;
printf( "Hello World\n" );
}
// Inversed while loop (executes at least once)
do {
input_data -= 1;
printf( "Bye World\n" );
if ( input_data_copy == 0 )
goto this_is_a_label;
} while ( input_data_copy > 1 );
this_is_a_label:
printf( "Jumped to label" );
return 0;
}

View File

@@ -0,0 +1,32 @@
int my_int; // Allocates memory on the stack.
// Variable is global (read / writable by entire program)
static int my_local_int; // only available locally (in this file)
const int MY_CONST = 10; // constant (immutable), convention: SCREAM_CASE
enum { ONE, TWO } num; // Enum. ONE will get value 0, TWO has value 1
enum { O = 2, T = 1 } n; // Enum with values specified
// Structs are like classes, but contain no logic
struct MyStruct {
int el1;
int el2;
};
int fun( int j ) {
static int i = 0; // Persists across calls of fun
short my_var = 1; // Block scoped (deallocated when going out of scope)
int my_var_dbl = (int) my_var; // Explicit casting (works between almost all types)
return i;
}
int main( int argc, char *argv[] ) {
if ( ( my_local_int = fun( 10 ) ) ) {
// Every c statement is also an expression, i.e. you can do the above!
}
struct MyStruct test; // Allocate memory on stack for struct
struct MyStruct *test_p = &test; // Pointer to memory where test resides
test.el1 = 1; // Direct element access
test_p->el2 = 2; // Via pointer
return 0;
}

View File

@@ -0,0 +1,3 @@
int main( int argc, char *argv[] ) {
return 0;
}

View File

@@ -13,3 +13,5 @@ This of course leads to \texttt{C} performing excellently and there are many pro
but instead optimized \texttt{C} code that is then compiled into machine code using a \texttt{C} compiler.
This has a number of benefits, most notably that \texttt{C} compilers can produce very efficient assembly,
as lots of effort is put into the \texttt{C} compilers by the hardware manufacturers.
There are many great \lC\ tutorials out there, a simple one (as for many other languages too) can be found \hlhref{https://www.w3schools.com/c/index.php}{here}

View File

@@ -1,4 +1,4 @@
\subsection{The Syntax}
\subsection{Basics}
\texttt{C} uses a very similar syntax as many other programming languages, like \texttt{Java}, \texttt{JavaScript} and many more\dots
to be precise, it is \textit{them} that use the \texttt{C} syntax, not the other way around. So:
\inputcodewithfilename{c}{code-examples/00_c/}{00_intro.c}
@@ -7,7 +7,6 @@ In \texttt{C} we are referring to the implementation of a function as a \bi{(fun
and to the definition of the function signature (or variables, without initializing them) as the \bi{(function) declaration} (or, correspondingly, \textit{variable declaration}).
\texttt{C} code is usuallt split into the source files, ending in \texttt{.c} (where the local functions and variables are declared, as well as all function definitions)
and the header files, ending in \texttt{.h}, where the external declarations are defined. Usually, no definition of functions are in the \texttt{.h} files
and the header files, ending in \texttt{.h}, usually sharing the filename of the source file, where the external declarations are defined.
By convention, no definition of functions are in the \texttt{.h} files, and neither variables, but there is nothing preventing you from putting them there.
\inputcodewithfilename{c}{code-examples/00_c/}{01_func.h}
\inputcodewithfilename{c}{code-examples/00_c/}{01_func.c}

View File

@@ -0,0 +1,14 @@
\newpage
\subsubsection{Control Flow}
Many of the control-flow structures of \texttt{C} can be found in the below code snippet.
A note of caution when using goto: It is almost never a good idea (can lead to unexpected behaviour, is hard to maintain, etc).
Where it however is very handy is for error recovery (and cleanup functions) and early termination of multiple loops (jumping out of a loop).
So, for example, if you have to run multiple functions to set something up and one of them fails,
you can jump to a label and have all cleanup code execute that you have specified there.
And because the labels are (as in Assembly) simply skipped over during execution, you can make very nice cleanup code.
We can also use \texttt{continue} and \texttt{break} statements similarly to \texttt{Java}, they do not however accept labels.
(Reminder: \texttt{continue} skips the loop body and goes to the next iteration)
\inputcodewithfilename{c}{code-examples/00_c/}{01_func.c}

View File

@@ -0,0 +1,37 @@
\newpage
\subsubsection{Declarations}
We have already seen a few examples for how \texttt{C} handles declarations.
In concept they are similar (and scoping works the same) to most other \texttt{C}-like programming languages, including \texttt{Java}.
\inputcodewithfilename{c}{code-examples/00_c/}{02_declarations.c}
A peculiarity of \texttt{C} is that the bit-count is not defined by the language, but rather the hardware it is compiled for.
\begin{fullTable}{llll}{\texttt{C} data type & typical 32-bit & ia32 & x86-64}{Comparison of byte-sizes for each datatype on different architectures}
\texttt{char} & 1 & 1 & 1 \\
\texttt{short} & 2 & 2 & 2 \\
\texttt{int} & 4 & 4 & 4 \\
\texttt{long} & 4 & 4 & 8 \\
\texttt{long long} & 8 & 8 & 8 \\
\texttt{float} & 4 & 4 & 4 \\
\texttt{double} & 4 & 8 & 8 \\
\texttt{long double} & 8 & 10/12 & 16 \\
\end{fullTable}
\drmvspace
By default, integers in \lC\ are \texttt{signed}, to declare an unsigned integer, use \texttt{unsigned int}.
Since it is hard and annoying to remember the number of bytes that are in each data type, \texttt{C99} has introduced the extended integer types,
which can be imported from \texttt{stdint.h} and are of form \texttt{int<bit count>\_t} and \texttt{uint<bit count>\_t},
where we substitute the \texttt{<bit count>} with the number of bits (have to correspond to a valid type of course).
Another notable difference of \texttt{C} compared to other languages is that \texttt{C} doesn't natively have a \texttt{boolean} type,
by convention a \texttt{short} is used to represent it, where any non-zero value means \texttt{true} and \texttt{0} means \texttt{false}.
Since boolean types are quite handy, the \texttt{!} syntax for negation turns any non-zero value of any integer type into zero and vice-versa.
\texttt{C99} has added support for a bool type via \texttt{stdbool.h}, which however is still an integer.
Notably, \texttt{C} doesn't have a very rigid type system and lower bit-count types are implicitly cast to higher bit-count data types, i.e.
if you add a \texttt{short} and an \texttt{int}, the \texttt{short} is cast to \texttt{short} (bits 16-31 are set to $0$) and the two are added.
Explicit casting between almost all types is also supported.
Some will force a change of bit representation, but most won't (notably, when casting to and from \texttt{float}-like types, minus to \texttt{void})
Another important feature is that every \lC\ statement is also an expression, see above code block for example.
The \texttt{void} type has \bi{no} value and is used for untyped pointers and declaring functions with no return value

View File

@@ -0,0 +1,43 @@
\subsubsection{Operators}
The list of operators in \lC\ is similar to the one of \texttt{Java}, etc.
In Table \ref{tab:c-operators}, you can see an overview of the operators, sorted by precedence in descending order.
You may notice that the \verb|&| and \verb|*| operators appear twice. The higher precedence occurrence is the address operator and dereference, respectively,
and the lower precedence is \texttt{bitwise and} and \texttt{multiplication}, respectively.
Very low precedence belongs to boolean operators \verb|&&| and \texttt{||}, as well as the ternary operator and assignment operators
\begin{table}[h!]
\begin{tables}{ll}{Operator & Associativity}
\texttt{() [] -> .} & Left-to-right \\
\verb|! ~ ++ -- + - * & (type) sizeof| & Right-to-left \\
\verb|* / %| & Left-to-right \\
\verb|+ -| & Left-to-right \\
\verb|<< >>| & Left-to-right \\
\verb|< <= >= >| & Left-to-right \\
\verb|== !=| & Left-to-right \\
\verb|&| (logical and) & Left-to-right \\
\verb|^| (logical xor) & Left-to-right \\
\texttt{|} (logical or) & Left-to-right \\
\verb|&&| (boolean and) & Left-to-right \\
\texttt{||} (boolean or) & Left-to-right \\
\texttt{? :} (ternary) & Right-to-left \\
\verb|= += -= *= /= %= &= ^=||\verb|= <<= >>=| & Right-to-left \\
\verb|,| & Left-to-right \\
\end{tables}
\caption{\lC\ operators ordered in descending order by precedence}
\label{tab:c-operators}
\end{table}
\shade{blue}{Associativity}
\begin{itemize}
\item Left-to-right: $A + B + C \mapsto (A + B) + C$
\item Right-to-left: \texttt{A += B += C} $\mapsto$ \texttt{(A += B) += C}
\end{itemize}
As it should be, boolean and, as well as boolean or support early termination.
The ternary operator works as in other programming languages \verb|result = expr ? res_true : res_false;|
As previously touched on, every statement is also an expression, i.e. the following works
\mint{c}|printf("%s", x = foo(y)); // prints output of foo(y) and x has that value|
Pre-increment (\texttt{++i}, new value returned) and post-increment (\texttt{i++}, old value returned) are also supported by \lC.

Binary file not shown.

View File

@@ -7,6 +7,8 @@
\usepackage{lmodern}
\setFontType{sans}
\newcommand{\lC}{\texttt{C}}
\begin{document}
\startDocument
\usetcolorboxes
@@ -58,7 +60,13 @@
\newsection
\section{The C Programming Language}
\input{parts/00_c/00_intro.tex}
\input{parts/00_c/01_syntax.tex}
\input{parts/00_c/01_basics/00_intro.tex}
\input{parts/00_c/01_basics/01_control-flow.tex}
\input{parts/00_c/01_basics/02_declarations.tex}
\input{parts/00_c/01_basics/03_operators.tex}
\input{parts/00_c/01_basics/04_arrays.tex}
\input{parts/00_c/01_basics/05_strings.tex}
\input{parts/00_c/01_basics/06_pointers.tex}
% ── Intro to x86 asm ────────────────────────────────────────────────