[SPCA] Finish pointers section

This commit is contained in:
2026-01-06 17:35:54 +01:00
parent 3574cbe4df
commit 623756af23
3 changed files with 45 additions and 2 deletions

View File

@@ -1,6 +1,12 @@
#include "01_func.h" // See a few pages up for declarations
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
void a_function( int ( *func )( char * ), char prompt[] ) {
( *func )( prompt ); // Call function with arguments
}
int main( int argc, char *argv[] ) {
int x = 0;
int *p = &x; // Get x's memory address
@@ -11,8 +17,7 @@ int main( int argc, char *argv[] ) {
int *null_p = NULL; // Create NULL pointer
*null_p = 1; // Segmentation fault due to null pointer dereference
// ── pointer arithmetic ───────────────────────────────────────────
// Already seen a bit in the c arrays section
// pointer arithmetic
int arr[ 3 ] = { 2, 3, 4 };
char c_arr[ 3 ] = { 'A', 'B', 'C' };
int *arr_p = &arr[ 1 ];
@@ -22,6 +27,11 @@ int main( int argc, char *argv[] ) {
char *arr_p_c = (char *) arr_p; // Cast to char pointer (points to first byte of arr[0])
printf( "%d", *( arr_p - 5 ) ); // No boundary checks (can access any memory)
assert( arr == &( arr[ 0 ] ) ); // Evaluates to true
int new_arr[ 3 ] = arr; // Compile time error (cannot use other array as initializer)
int *new_arr_p = &arr[ 0 ]; // This works
a_function( &get_user_input_int, c_arr );
return EXIT_SUCCESS;
}

View File

@@ -13,6 +13,39 @@ Of note is that if you simply declare a pointer using \texttt{type * p;} you wil
The (Linux)-Kernel randomizes the address space to prevent some common exploits.
\inputcodewithfilename{c}{code-examples/00_c/00_basics/}{05_pointers.c}
\newpage
\begin{scriptsize}
Some pointer arithmetic has already appeared in section \ref{sec:c-arrays}, but same kind of content with better explanation can be found here
\end{scriptsize}
Note that when doing pointer arithmetic, adding $1$ will move the pointer by \texttt{sizeof(type)} bits.
You may use pointer arithmetic on whatever pointer you'd like (as long as it's not a null pointer).
This means, you \textit{can} make an array wherever in memory you'd like.
The issue is just that you are likely to overwrite something, and that something might be something critical (like a stack pointer),
thus you will get \bi{undefined} behaviour! (This is by the way a common concept in \lC, if something isn't easy to make more flexible
(example for \texttt{malloc}, if you pass a pointer to memory that is not the start of the \texttt{malloc}'d section, you get undefined behaviour),
in the docs mention that one gets undefined behaviour if you do not do as it says so\dots RTFM!)
As already seen in the section arrays (section \ref{sec:c-arrays}), we can use pointer arithmetic for accessing array elements.
The array name is treated as a pointer to the first element of the array, except when:
\begin{itemize}[noitemsep]
\item it is operand of \texttt{sizeof} (return value is $n \cdot \texttt{ sizeof(type)}$ with $n$ the number of elements)
\item its address is taken (then \texttt{\&a == a})
\item it is a string literal initializer. If we modify a pointer \texttt{char *b = "String";} to string literal in code,
the \texttt{"String"} is stored in the code segment and if we modify the pointer, we get undefined behaviour
\end{itemize}
\shade{orange}{Fun fact}: \texttt{A[i]} is always rewritten \texttt{*(A + i)} by compiler.
Another important aspect is passing by value or by reference.
You can pass every data type by reference, you can not however pass an array by value.
Another interesting concept that \lC\ has to offer is body-less loops:
\begin{code}{c}
int x = 0;
while ( x++ < 10 ); // This is (of course) not a useful snippet, but shows the concept
\end{code}
\lC\ also has an option to pass functions as arguments to functions, called function pointers.
A function is passed using the typical address syntax with the \verb|&| symbol is annotated as argument using \verb|type (* name)(type arg1, ...)|
and is called using \verb|(*func)(arg1, ...)|.

Binary file not shown.