How to CS429
When to CS429
Why to CS429
Where to CS429
What to CS429
CS429 Discussion Section #2
ONLY YOU CAN PREVENT
CS MACHINE OUTAGES
To fix Disk Quota Issues… In VSCode, open settings using:
Ctrl + , or Cmd + ,
Search for…
1. C_Cpp: Max Cached Process and set it to 2
2. C_Cpp: Intellisense Cache Path and set it to
/tmp/<csid>/vscode-cpptools (replace <csid>
with your UTCS ID)
3. C_Cpp: Intellisense Cache Size and set it to 128
VSCode
If you are using VSCode, the C/C++ extension is VERY helpful
- Code auto-complete
- Ctrl+Click lets you follow function and object declarations
- Other useful stuff
If you don’t have it installed, it is highly recommended
Turn on Autosave too!! (File → Autosave)
If you’re not using VSCode… why are you not using VSCode.
Quiz
● Open Note
● Open Internet
● NO CHATGPT
● NO RUNNING CODE
● MUST BE TAKEN IN YOUR DISCUSSION SECTION
● MUST BE TAKEN IN-PERSON!
● Good Luck :)
Hexadecimal, Octal, and Binary
● Different bases, same value
● Binary: base 2, 0’s and 1’s. This is how electronics work (ON and OFF)
● Octal: Groups of 3 binary digits. Helps us work with longer numbers
● Hexadecimal: Groups of 4 binary digits. Really convenient as 1 byte is 8 bits, which is 2 hex digits
● Notation: 0x for hex, 0b for binary, prefixed with 0 for octal
● Conversion practice: Convert to other bases:
● 0x100 to Binary and Decimal _______________________________________
● 1234 to Hex and Binary ______________________________________________
● 0b1101 0011 0100 1011 to Hex and Decimal ________________________________
a55
Decimal >
-
hex binary
-
take , divide
number by 16
11 11
divide by f
-
9(
take Quotient
->
digit
/
123 &
dec : 8 12345678910"11314iS
0123456789ABCDEF
1038100 her
-
binary
=
00000001 0010 Doll %loo old allo all 1000 loo) loo lol 1100 11011110 IIII
Ox 100 -
It st
Or 1 1
J
not To 100
-
100
256
↓
160 ·
0 + 161 .
0 + 165 .
1 = 256
S432120
bin : 101011
dec : 20 :
1 + 201 + 40 + 23 . 1 + 24.0 + 2%
120 8 ⑧ 36 = 43
617r0
LT34
E
dec : 123 I
308r
bir ↓ . G T . . .
010
ish -0
3 .
--
308
&
hax 77rt
Y
4 r 13
16 E
4
D2
or
50 97 + 10 diff numbers [0 17 - 2
, , number
10
Positional Representation ⑦ =
4 + 2 + 1
= ( x22 + 1 x 2) + 1x2
● All of these bases are “radix” systems, also known as “positional” = 111- binary
representation.
● Each place value is valued at a power of some radix (the base)
123 =
100 + 20 + 3
+100 240' + 3 -
=
Missing negative
numbers !
K-bit number
k - 1
k 2
1 O
-
x 2 + 102 +... + 1x2
Kal
Negative Numbers =
22 =
2 -1
- -
IG
so ,
(2-11]
● Numbers can be unsigned (magnitudes) or signed (positive or negative)
● How to represent them? Two methods come to mind
I I
● Sign bit
○ Leads to issues with multiple “zero”s 8 2k -
1
○ Arithmetic doesn’t natively work when adding negatives
● Two’s complement I
b
1
I
2k zk -
- -
○
○
Preserves positional notation (MSb is now just a negative O
Has signed overflow - undefined behavior!
place value)-
2k 1 -
k 1
zk
- 1 -
Z
-
11 O I O 01
I
110 1100 1
X
-
1 x 18 64
+ + 16 + 8 + 1
= - 128 + 80 +8 + 1 = 128 + 89 = -
39
q
0101,00 1
q
>
-
27
01 1 1
=2 -
. .
chicht
O
...+ 2
↑
z complements Flip
10 + 01010
2 com
+
1010101 - 1
M + 1
6
-
6 ->
1010 -
0101 >
-
0110
-
8 +2
Working with Two’s Complement
- · o 1
01 0 I
10 - 10 flip bits
● &
How to negate a number? “Twiddle x plus one”. (~x+1)
#
● Works with any bit-width of number–chars, ints, longs, and more.
● What are the limits? What is the largest positive/negative representable integer with n bits?
● Conversion practice: Negate these numbers. ~
8 +y + 1
- = -
3
+7
● 0b0011 > -
0011 = 3 0011-
> 1100 - 1101
● 0b01001011
● 25 (as an 8-bit number) 10, 2" -
1723 [0 ,
71
● 1 (as a 64-bit number)
[2k 1 2k- 1]
-
● 1 (as a 32-bit number) -
k = #08 bils
,
unsigned
10 -
01010 -
00001010
um
Integer Sizes signed
a
8-bit
-
10 >
-
10110 - >
11110110
~
18 -
● In the real world, numbers can be infinitely big. In computers, we have finite sizes
● We often need to convert between different integer sizes (char, short, int, long)
- - - -
● How does this work for unsigned? T --
○ Simple, just add 0’s (extending) or chop off bits (truncating)
○ Might lose data when truncating, so we should avoid going from larger to smaller datatypes
● How about for signed two’s-complement?
○ We have to use sign extension 4 bit it 4 bit 2 bit
2
○ Copy MSb to extend the number
1010 - 10 0010 >
-
16
w u
● Conversion Examples:
● Extend 25 (unsigned, 8 bit) to 16 bits. Also truncate it to 4 bits.
● Extend -25 (signed 2C, 8 bit) to 16 bits. Also truncate it to 4 bits.
unsigned k= 5 31 >
-
06/1111
- 2
⑬ 1
33
i
>
-
O
3132
16 ; =
unsigned
unsigned
=
int x
2's comp int X =
16 ; =
2's comp
-
I >
-
11111 15 -
01111
S white if1 T
ooool
&
--8
black if0 -
=
16 - 000
00000
Signed and Unsigned Numbers &
16 + O
S igned
-
● Aka “the wheel” >
- -
1 O
(of death)
● Signed numbers are
stored in two’s
complement form
↑
-
1615
Bitwise Operations
01110100 01110100 01110100 01110100 01110100
>> 5 << 4 & 00111000 ^ 00111000 | 00111000
00000011 01000000 00110000 01001100 01111100
Logical and Arithmetic shifts
- Logical: shift and replace bits with 0
- Arithmetic: shift and replace bits with sign bit (sign extend)
- Left logical/arithmetic are the same (replace with 0)
What do shifts actually do? (hint: powers of 2)
Back to Systems: Memory
● Local variables and function arguments are placed on the stack
○ Deallocated after the variable leaves scope
○ Never return a pointer to a stack-allocated variable
○ Never reference the address of a variable outside its scope
● Memory blocks allocated by calls to malloc/calloc are placed on the heap. This is
comparable to new in Java.
○ int* a = malloc(sizeof(int)); // a is a pointer stored on the
-
stack to a memory block within the heap
○ free(a);//frees the memory allocated pointed to by a (C DOES NOT
HAVE A GARBAGE COLLECTOR!)
%
-
%(4)
Dynamic Memory Allocation
]
● Handle dynamic memory allocation on heap >
-
● void* malloc (size_t size);
○ Allocate block of memory of size bytes
○ Does not initialize memory
● void* calloc (size_t num, size_t size);
○ Allocate block of memory for array of num elements, each size bytes long
○ Initializes memory to zero
-
● void free(void* ptr);
-
○ Frees memory block pointed by ptr
*
●
○ Use exactly once for each pointer you allocate
size: number of bytes you want, can use sizeof operator
int arr =, -
.
-
○ Careful though, sizeof might not work the way you expect on strings!
○ sizeof only works on statically-allocated arrays, not dynamic!
↓ Yalloc (40)
Deep Copy
* pt- D
+
-
#pr
Shallow
Copy
part
*
/
/ char *
str = malloc
Apts ↓
str = "aba"
Shallow
Week 2 chart stre = Stri
copy->
extending your program to handle
strings
OX :
ci"abc" + "de"
"abc" *2 + abcab
freeing shing copies
cleanup()
beeing all
dynamically allo
Nodes&
string
J
free(str) ;
free(stre) ; + Double free make spac
u
& & using mullo to make
space
Strapy(str1 ,
Str2) ;
2) Use
strapy to
copy contents
strien - looks for "10" character at end
# ~malloc (100 (int)]
char s =
"aba" ;
size
of
Sile = len(S) + 1
075 Pull terminator
Debugging Memory Leaks with Valgrind
● Allows you to identify which memory allocations are never being freed
● valgrind --log-file=val_log --leak-check=full ./ci -i tests/<testname> >
/dev/null
● Output will be stored in a file “val_log”
#
Tools for C Programs: gcc
● GNU Compiler Collection (gcc) is a toolchain that wraps useful programs together -- we use it to compile C
code.
○ The command you will want to remember to compile programs:
■ gcc -o <filename> <filename>.c
● -o specifies the output filename, which is a.out by default
○ With flags, we can see the actual pipeline it goes through when compiling C (preprocessing, compiling, assembling, and
linking). Later in the semester you’ll go into detail on that pipeline.
■ -save-temps will stop GCC from removing the temporary files at each stage of the pipeline
○ Other flags
■ -g will produce debugging information for GDB debugger to use -- it will be necessary if you want to debug your
code with gdb
■ -Wall will enable some warnings, while -Werror will make all warnings into errors
Tools for C Programs: Makefiles
● Makefiles automate the building of programs
○ You’ll run into these during your projects in this class and probably OS as well.
○ Makefiles consist of a series of targets, which are just a couple of commands to run in succession. They’re most
commonly used as a shorthand for compiling a large
project with all the correct files and flags.
○ To tell a makefile to build a program, go to its directory
and enter the command make <target>
■ Different makefiles may create flags you can pass in to build a program differently
■ Typically, this includes:
● make clean
● make all
● make run
● make test
Thanks for coming!
We’ll hang around to answer any questions.
Extra Slides: C Crash Course
C Topics
● Introduction to C for Java programmers
○ Primitive types
○ Arrays and strings
○ Pointers
○ Variable declaration
○ Casting
○ structs
○ Unions
● Tools for C programs
○ Makefiles
○ gcc
○ gdb
Intro to C for Java Programmers: Primitive Types
● Primitives in C are similar to Java.
○ int, short, long, float, double, and char are all C primitives that are roughly the same as their Java
counterparts.
○ Notably, C lacks byte and boolean.
○ Booleans (in C, bool) can be added with the inclusion of the stdbool library.
○ Notable differences between Java and C primitives:
■ All integral types (char, short, int, long) can be signed or unsigned .
■ chars can be signed, unsigned , or “plain”
● Plain chars are either signed or unsigned depending on implementation -- do not rely on
them to be one way or the other!
■ int can be specified to be short, long, or long long , which effectively changes it to the
specified type.
Intro to C for Java Programmers: Arrays and Strings
● Arrays in C are also similar to Java.
○ They are declared slightly differently:
■ int A[10];
○
○
Likewise, 2D arrays are legal:
■ int B[2][3]; H
It is important to keep in mind that arrays are contiguous in memory.
-
● Strings in C are functionally a one-dimensional array of characters that ends with the null
terminator: hex character 0x0 or escape code ’\0’.
○ C starts at the beginning or the array (or wherever you tell it to start, really), and will assume the string ends
at the null terminator.
○ All standard library functions assume null-termination.
● Important String functions: strcpy(), memcpy(), strlen(), strcat()
--
Intro to C for Java Programmers: Pointers
● Pointers are variables that store the address of another variable. For our
purposes, they will usually be 8 bytes (64 bits) long (word size).
○ Pointers can point to other pointers: for example, an arrays of strings.
○ There are two pointer operators you need to be familiar with:
■ Unary ampersand (&x) will return the address of the variable
■ Unary asterisk (*y) will return the value at the address held in the
variable
○ Pointers themselves are declared by declaring the type of the variable it points
to, followed by an asterisk.
■ int *x and char* y are both valid, as the space between the type
and the variable name can be on either side the asterisk.
■ Pointers to other pointers follow suit: char **s .
-
*
**- Char
S
char
Intro to C for Java Programmers: Pointers on Pointers
● The compiler needs to know the type of the variable stored at an address
○ You may see void * as an argument, but it generally can’t be messed with unless you cast it to a different
type of pointer.
● Dereferencing NULL causes undefined behavior (usually a segfault).
Intro to C for Java Programmers: Casting
● Casting looks the same as it does in Java, but doesn’t typically alter memory.
○ The actual bytes under the hood tend to stay the same
■ Exceptions may include conversion to floating-point types
○ Conversion from larger types to smaller types will truncate bytes, while conversion from smaller types to
larger types will append bytes -- sometimes, bytes you don’t actually want to access
● char* ptr = (char *)malloc(sizeof(str)+1);
-
↑ a
void
returns
Intro to C for Java Programmers: Why Pointers?
● Unlike Java, functions in C are
○ Pass by value or pass by reference?
○ pass-by-value: every argument passed to a function is copied. This means that if we were to pass in the variable
itself, we would really only be operating on its value, and we would fail to actually update the variable.
○ We solve this by passing pointers to the variables we need to update and playing the reference/dereference
game to update their actual values
■ Also used to avoid creating multiple copies of large structs/other datatypes
○ A lot of functions in C have void returns, and this is because the program state is changed through
pass-by-reference
Intro to C for Java Programmers: Variable
Declarations
● Local variables are defined inside of functions and are seen only by their parent function
● Global variables are defined outside of functions and are seen by all files
○ Use the extern keyword for global variables defined in other files
● const variables are for variables that won’t change -- think final in Java
● static variables keep their value between function calls
Intro to C for Java Programmers: structs
● structs are collections of values grouped under one name, but the values are not necessarily adjacent in
memory.
○ Accessing a struct’s members can be done with the dot operator similar to Java
■ struct.field
○ Accessing a struct pointer’s members is done with either a dereference followed by dot or it can be done with the arrow
operator
■ (*ptr).field
■ ptr->field
Intro to C for Java Programmers: unions
● unions allow for storing different types at the same location.
○ A union is the size of its largest variant, but it can contain one of any of the types it is declared to have.
○ Accessing unions is done with the dot or arrow operator like structs
■ Since the union can only contain one of the types, modifying one of its variants will modify all of its variants.
● structs and unions can contain other structs and/or unions.
Intro to C for Java Programmers: Defining Derived
Types
typedef union{
typedef struct NODE{ char cval;
struct NODE *prev;
int ival;
value_t val;
value_type_t type; bool bval;
struct NODE *next; char *sval;
} node_t; } value_t;
Complete C Crash course:
https://www.sololearn.com/learning/1089
Intro to C for Java Programmers: strings
● In C, “strings” are actually just arrays of char s. There’s no object called a “String ” like in Java.
● The type of a string is char[] or equivalently, char * .
○ Why are these equivalent?
● Importantly, strings in C have a “null terminator”, which is a byte at the end of the string that has a value of 0.
● In other words, a string is defined as an array of characters terminated by a null character.
○ What can happen without this null terminator?
○ How does strlen() work?
● Library functions: strlen, strcpy, strcat . Strcpy and Strcat do copy null terminators (but remember
to allocate enough space!)
Helpful Demos for Learning C
● https://github.com/noah-kuhn/LinkedListDemo/
● https://github.com/noah-kuhn/DebugDemo/
● https://github.com/CS429-S2022/CS429_Discussions/tree/main/discussion2