2026-03-14
// in file 1
int arr[10];
// in file 2
extern int *arr;This is semantically incorrect and leads to an access violation. It
thinks that arr holds the contents to the pointer. Making a
reference to arr[i] is equivalent to saying that start at
wherever arr points, move over i places using
the contents of arr[0..8] as the pointer value.
Instead just declare it with extern int arr[].
This is READ-ONLY memory as it is hardcoded to the
.text section of the binary! Trying to deref it at runtime
is a page-fault in most cases since that section of the binary is marked
read-only by the OS.
On the other hand, if they are initialized by an array, then you can see in the disassembly that they are actually loaded on the stack and can use it.
They need to have the names libname.so where
name is what you link with -lname.
LD_LIBRARY_PATH and LD_RUN_PATH are used for
static and dynamic linking respectively.
That is to say,
void f(int * const p);is valid. However, the above example is meaningless as the pointer is
copied into the function. It makes sense for int const * p
as that implies that the underlying data is constant.
Volatile is for raw hardware and basically means a value should be looked up from hardware.
Used for function optimization. If a pointer is an argument to a function, then the function is not aliased at all, atleast never written into. Mostly used as a hint to the compiler. However, it better not be used unless you're sure what you're doing.
You can optionally specify padding bytes in struct fields and also limit their size to a fixed number of bytes. Once again, useful in embedded.
If you have a pointer to a struct that is =NULL=, but you use the
-> operator to get a member and then take its address,
it will give the size of the member. Basically acting as if the member
is stored at memory 0.
Another thing to note would be the fact that the pointer to the first member of the struct is also the pointer to the struct.
Better yet, just use offsetof macro.
Just like structs, if the composing members of the union all have the
same type, say int, then the pointer to the union is also a
pointer to the int, no matter which one of the variants was set
last.
Some ancient feature you shouldn't be bothered about. Basically
??! getting converted to pipe symbol and other
shenanigans.
#include <stdio.h>
void print_matrix(int h, int w, int m[h][w])
{
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++)
printf("%2d ", m[row][col]);
printf("\n");
}
}
int main(void)
{
int rows = 4;
int cols = 7;
int matrix[rows][cols];
for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++)
matrix[row][col] = row * col;
print_matrix(rows, cols, matrix);
}