mirror of
https://github.com/janishutz/eth-summaries.git
synced 2026-01-11 01:18:27 +00:00
[SPCA] Finish pointers section
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
Reference in New Issue
Block a user