61C-P1-C
Compile
gcc hello.ccreates machine language codea.out loads andexecutes program
great idea in C:
![[Pasted image 20240519124500.png]]
basic grammars
input
1 |
|
Combined, argc and argv get the main function to accept arguments.
- argc will contain the number of strings on the command line (the executable counts as one, plus one for each argument). Here argc is 2:
./a.out myFile- argv is a pointer to an array containing the arguments as strings (more later re: pointers and strings).
output
1 |
|
%X is for hexadecimal (16-dimension) numeral
Everything on your computer is bits.
basic types
| Type | Description | Example |
|---|---|---|
| int | Integer Numbers (including negatives) | 0, 78, -217, 0x7337 |
| unsigned int | Unsigned Integers (i.e., non-negatives) | 0, 6, 35102 |
| float | Floating point decimal | 0.0, 3.14159, 6.02e23 |
| double | Equal or higher precision floating point | 0.0, 3.14159, 6.02e23 |
| char | Single character | ‘a’, ‘D’, ‘\n’ |
| long | Longer int, Size >= sizeof(int), at least 32b | 0, 78, -217, 301720971 |
| long long | Even longer int, size >= sizeof(long), at least 64b | 3170519272109251 |
| boolean: true&false | ||
| false: |
- 0 (for ints, all varibles are 0)
- NULL(pointers)
more features
constants in C
const int a = 1; assigned the 1 to a in the declaration and never change it throughout the program#define a 1 give 1 to a prior to all of the compilation process
typedef
defining new types are allowed.
1 | typedef uint8_t BYTE; |
struct
strurcted objects
1 | typedef struct { |
control flow
the same as that in Java!
pointers
memory
memory is basically a big single-array.
A pointer refer to the location of the memory.
pointers
1 | int *p; // tell that the p refer to a pointer to a int memory box |
usage
Pointers are useful when passing parameters.
1 | void addOne (int x) { |
good ones:
1 | void addOne (int *p) |
common bugs: garbage address
Local variables in C are not inialized!
Therefore, they can be anything.
structs
1 | typedef struct { |
arrays
just a big block of memory!
declaration and ini: the same as that of java
pointers for arrays
a[i] ⟺ *(a+i) they are equal!
pointer changing
wrong code:
1 | void increment_ptr(int32_t *p) |
printed: q = 50!
remember: C is pass by value!
Instead, pass a pointer to a pointer (“handle”).: Declared as data_type **h.
right code:
1 | void increment_ptr(int32_t **h) |
common pitfalls
constant using of an number
Wrong
1 | int i, ar[10]; |
Strongly encouraged
1 | int ARRAY_SIZE = 10; |
arrays VS pointers
char *string = char string[]
accessing array elements:arr[0] is equal to *arrarr[2] is equal to *(arr+2)
other features
- array bounds are not checked during the element access!
- An array is passed into functions as a pointer
- declared arrays are only allocated while the scope is valid.
Strings
An array of characters,followed by a null terminator. aka \0
C have a branch of functions for string:
strlen: computes the length of a stringstrcpy: copy a string from one to another
endianness
“little endian”: the least significant byte of a value is stored first
“big endian”: contradict to little ones
memory
sizeof(): gives size in bytes of types of varible
address space
- Stack: local variables inside functions, grows downward
- Heap: space requested via malloc(); resizes dynamically, grows upward
- Data (Static Data): variables declared outside main, does not grow or shrink
- Text (aka code): program executable loaded when program starts, does not change
- chunk is unwriteable/unreadable so you that crash on NULL pointer access
![[Pasted image 20240520110032.png]]
Programming in C needs to know the memory!
Global: stored in data frame
local: stored in the stack, and then released after the function have been used.
stack
every time a function is called, the stack is established.
Last in, first out!
pointers in the stack
It is ok and fine to pause pointers outside into the stack
However, it is bad to return a pointer to sth. in the stack!
heap
dynamic memory–>> the stack!
specify number of memory can be allocated/disallocated
malloc(): Allocates raw, uninitialized memory from heapfree(): Frees memory on heapealloc(): Resizes previously allocated heap blocks to new size
malloc()
return void * pointer to blocks of memory
allocate a sturct:
1 | typedef struct {} TreeNode; |
allocate an array of 20 ints:
1 | int *ptr = (int *) malloc(20*sizeof(int)); |
free()
dynamically free the memory
1 | int *ptr = (int *) malloc... |
realloc()
resize a previously allocated block at a new size
![[Pasted image 20240521110437.png]]
⚠
Memory can be allocated / deallocated at any time!
- “Memory leak”: If you forget to deallocate memory
- “Use after free”: If you use data after calling free
- “Double free”: If you call free 2x on same memory
memory leak
the failure to free()!
use after free
1 | struct foo *f; |
double free
1 | struct foo *f = (struct foo *) malloc(10*sizeof(struct foo)); |
forgetting realloc()
realloc() copy the data into a different part of the heap.
more pointers
function pointers
int (* fn) (void * , void * ) = &foo;
fn is a function that accepts two void * pointers and returns an int and is initially pointing to the function foo.(* fn)(x, y); will then call the function
example:
1 | /* map a function onto int array */ |
generic functions
why? – we want to write general-purpose code
generics:
- Should generally work regardless of argument type
- Update blocks of memory, regardless of data type stored in those blocks
one example:
![[Pasted image 20240527174041.png]]
generic memory copying
To access some number of bytes in the memory, we use 2 generics in the String standard library:
void *memcpy(void *dest, const void *src, size_t n):- copy n bytes from memory area
srcto memory areadest, return a pointer todest
- copy n bytes from memory area
memmove(void *dest, const void *src, size_t n):- copy n bytes from memory area
srcto the memory areadest, return a pointer todest.
use memcpy for performance reasons!
- copy n bytes from memory area
example: swap
consider swap
some swaps:
1 | void swap_int(int *ptr1, int *ptr2) { |
consider other swaps: short swap, string swap, char swap…
void* swap can be a “general swap”!
1 | void swap(void *ptr1, void *ptr2, size_t nbytes) { |
another example: swap_ends
1 | void swap(void *ptr1, void *ptr2, size_t nbytes) {…} |
