Skip to content

Latest commit

 

History

History
382 lines (249 loc) · 10.6 KB

C.md

File metadata and controls

382 lines (249 loc) · 10.6 KB

C cheatsheet and random shit...

Resources

C-Faq How I program C - Eskil Steenberg

Harder,Better, Faster, Stronger code Crafting interpreters Linux Container in 500 lines Simple memory alocator Learning C projects ideas Gustedt blog

Bookz

https://freecomputerbooks.com/ C in depth

Notes on C

Scope

You can have a scope without anything to isolate variables from their outer scope.

int main() { int i = 2; printf("%d", i); { int i = 4; printf("%d", i) } printf("%d", i); } // 242\0

C language has the concept of variable scope. Ina a nutshell, each pair of { and } introduce new scope, and variables are bound to those scopes. You can declare variables with the same name, as long they are in different scopes.

Redeclaring variables in C - Stack Oveflow

Storage classes

Specifier Storage Initial Value Scope Life
auto Stack Garbage In block End of block
extern Data Segment Zero Global Program life
static Data segment Zero In block Program life
register CPU Register? Garbage In block End of block

Extern

Use of extern to share variables between source files - Stack Overflow How to correctly use the extern keyword in C - Stack Overflow

Extern keyword can be used inside a function. It informs the compiler the variable is not in the same file. We usually declare extern variables in the .h so we don't need to use that keyword.

/* main.c
** gcc main.c 2.c -o extern
*/
int main() { extern int a; a = 5; f();}
// 2.c
int a; f() { printf("%d", a); }

Since functions are visible throughout the program by default, the use of extern is not needed in function declarations or definitions. Its use is implicit. When extern is used with a variable, it's only declared, not defined.

When extern is used with a variable, it’s only declared, not defined. As an exception, when an extern variable is declared with initialization, it is taken as the definition of the variable as well.

Automatic

Variables in function scope are implicitly declared as automatic (auto).

Static

static inline int pow(int n) { return n * n; }

Don't confuse static used in function scope with static used in the global scope. It means the variable can only be accessed from that file.

Memory

Virtual addresses

In all modern OSes (Windows, Linux, BSD, etc), all addresses in a userspace application are virtual addresses. The exceptions to this are certain RTOSes or other custom bare-metal applications.

Segments

Do pointers refer to physical or virtual memories

Ld is responsible for making the segments mapping and setting rwx permissions.

Segment Description
Text Executable instructions
Data Global and static variables with predefined values
BSS Undefined global and static
Stack LIFO. Converges to Heap.
Heap Dynamically alocated variables. Converges to Stack
char *a = "ABCD"; // .rodata (modifying causes SIGSEGV)
char b[] = "ABCD"; // Data

int c; // BSS

int main() {
        static int d; // BSS
        char *d = "ABCD"; // .rodata (modifying causes SIGSEGV)
        char e[] = "ABCD"; // Stack
        char *f = strdup("ABCD"); // Heap
        // <- code instructions in Text

.rodata

Some compilers also use a data segment called .rodata as in read-only data to store string literals and sometimes const.

How to see segments mapping

(gdb) info proc
process 8596
cmdline = '/home/guy/blog/string_elf/a.out'
cwd = '/home/guy/blog/string_elf'
exe = '/home/guy/blog/string_elf/a.out'

(gdb) shell cat /proc/8596/maps
00400000-00401000 r-xp 00000000 fd:02 134817229 ...
00600000-00601000 r--p 00000000 fd:02 134817229 ...
00601000-00602000 rw-p 00001000 fd:02 134817229 ...

[From Rodata to RwData - https://guyonbits.com/from-rodata-to-rwdata-introduction-to-memory-mapping-and-ld-scripts/]

Symbols

Without adres randomization (ASLR), the variable address is exactly the same as the one found in the symbol table.

$ gcc code.c -no-pie -o executable
$ objdump --syms executable | grep variable
0804a020 g     O .bss	00000004              variable
printf("%p", &variable); // 0x804a020

Executable stack

-z execstack marks the object as requiring executable stack.

-fstack-protector allocates a little more space on the stack and adds a stack guard (canary) to protect against buffer overflows.

Preprocessor

#define FORTYTWO 42
int main() { int i = FORTYTWO; } // gcc -E fortytwo.c

[Can gcc output code after preprocessing? - Stack Overflow]

Macros

We need to protect macro with parenthesis otherwise we can get non-desired results such as :

#define ABS(x) x<0?-x:x // e.g. abs(2-3) translates to 2-3<0-2-3:2-3 -> -5

It is also better practice macros with* *do {...} while (0)**:

do {...} while (0) in macros

Debug Macro

#define DEBUG(fmt, ...) do { fprintf(stderr, fmt) } while(0) 
#### Offset Macro
#define offsetof(st, m) \
    ((size_t)&(((st *)0)->m))

Ofsetof - Wikipedia

#ifdef DEBUG
# define DBG(x) do { (X) } while(0);
# else
# define DBG(X)
# endif

Types

printf("%d", sizeof('A')); // 4

Integers promotions

Type conversions

Floats

What every programmer needs to know about floats - Oracle

Arrays

Plain array decays to a pointer to its first element, it's equal to &array[0].

Why are arrays and array pointing to the same address?

Array initialization

int array[] = {1, 2, 3, 4, 5 }; 						// 1, 2, 3, 4, 5
int array2[5] = {1, 2};         						// 1, 2, 0, 0, 0
int array3[5] = {1, };          						// 1, 0, 0, 0, 0
int array4[5] = { [0 ... 1] = 1, [2 ... 3] = 2 };   				// 1, 1, 2, 2, 0
int array5[] = { [0 ... 2] = 1, [2 ... 3] = 3, [ 1 ... 4 ] = 5 }; 		// 1, 5, 5, 5, 5
int array6[] = { [4] = 1, [1 ... 2] = 1, [2 ... 3] = 2, [1] = 8, [1] = 9 }; 	// 0, 9, 2, 1

Negative array indexes

int	main()
{
	int	array[4] = {1, 2, 3, 4};
	printf("%d", (array + 4)[-4]); // prints '1'
}

String literals VS Arrays

char *s_array[] = "ABC"; // equivalent to char s_array = {'A', 'B', 'C', '\0'}. On stack if automatic variable.
char *str = "ABC"; // .rodata if compiled with gcc (read-only memory)

String Literals. Where do they go? - StackOverflow

Variable Length Array

VAL were introduced in C99 standard.

scanf( "%d", &numElements);
if(numElements <= 0) return ;
double data[numElements];

VLA Gnu Extension

Struct

Many ways to declare a struct

Anonymous struct

Unions

The memory occupied by a union will be large enough to hold the largest member of the union.

The infamous *(machine dependent)*union trick

typedef union {

	int i;
	struct {
		char b1; // LSB
		char b2;
		char b3;
		char b4; // MSB
	};
} u_integer;

int main() {
	u_integer integer;
	integer.i = 0xFF;
	printf("%d\n", integer.i); // 255 == 0xFF
	integer.b2 = 0xFF;
	printf("%d\n", integer.i); // 65535 == 0x0000FFFF
	return (0);
}

Functions

Variable arguments list

How Variable arguments list work in C

Restrict

void f(int *restrict a, int *restrict b) {
    *a += *b;
    *b += *a;
}

// ...
int a = 2;
f(&a, &a); // returns 6

gcc -O3 restrict.c -o restrict

[https://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html](Desmitifying the restrict keyword)

Branchless programming

Branchless programming examples

Threads

I/O

Unit testing

The assert Macro

https://stackoverflow.com/questions/2486386/why-do-i-see-throw-in-a-c-library assert.h source code from glibc

GCC

Fortify source

Fortify source 1 and 2 - StackOverflow

Misc

Pragma

Anybody who writes #pragma pack(1)...

Coma operator

    if (1, 2, a = b) printf("Wow?");

(The Comma Operator - Wikipedia)[https://en.wikipedia.org/wiki/Comma_operator]

Rand0m

When to open file in binary mode

Use 'b' mode, to read/write binary data as is without any transformations such as converting newlines to/from platform-specific values or decoding/encoding text using a character encoding.

Printf buffers

Random things to investigate

https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule

Compression algorithms - Michael Dipperstein's Page O'Stuff

Strict aliasing rule https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule

How to continue execution after a SIGSEGV https://stackoverflow.com/questions/3291382/coming-back-to-life-after-segmentation-violation

Unit testing, Unit testing macros