[CS50] Week 4 Section
1. Pointers (and why to use them)
- A variable : a name for some value that can change → has an address somewhere in memory
- type : int *
- name : p
- value : &calls (the address of calls)
Reasons to use pointers
Pointers enable additional capabilities like:
- You could write a function that allows you to pass something in by reference and not just by copy.
The code you write is cleaner as a result. - You could ask your program for dynamic memory depending on what the user actually needs.
Your programs can now scale their usage of memory according to user behavior.
2. Passing by Copy vs Passing by Reference
<Passing by Copy>
This seemed to be swapped in swap, but it's still the same in main function !
<Passing by Reference>
By copying the addresses of a and b(the pointer to a/ the pointer to b), we actually copy in the address, and we change the values exactly where those values currently in memory.
Let's debug this in VS Code and see step-by-step:
Here's my code swapping two values, a and b.
If I run debug50 :
① Notice that a = 10, b = 50
Let's step into the swap function!
② In variable window, you can see the addresses of a and b now. (&a, &b)
Let's step over :
③ Notice that the value of location a(*a = 10) is handed over to temp.(temp = 10)
Let's step over:
④ Now, the value of b(*b = 50) is handed over to a.(*a = 50)
Let's step over for the last time :
⑤ Notice that the value of temp(10) is handed over to *b.(*b = 10)
And now you can check that a and b are swapped.
3. FILE I/O
We can also open up files, read data from them, and write data to those files!
fopen | opens a file for future reading/ writing. |
fclose | closes a file. |
Always fclose all files you fopen!
"r" means 'read' mode.
"w" means 'write' mode.
<Reading and Writing>
fread | reads data from a file into a buffer*. |
fwrite | writes data from a buffer* to a file. |
*a buffer is a chunk of memory that can temporarily store some data from the file.
Why do we need a buffer?
→ We often don't know how big a file is, so the best we can do is to look at small bits of it, not the entire file itself.
<Reading from a File>
- From where are you reading?
- To where are you reading?
- What size is each block of data you want to read? (ex. text file-1 byte/ image file-3 bytes)
- How many blocks do you want to read?
fread(Towhere, what size , how many , Fromwhere);
ex) fread(buffer, 1, 4, f);
<Practice with Reading>
- Create a program, pdf.c, that opens a file given as a command-line argument.
- Check if that file is a PDF. A PDF always begin with a four-byte sequence, corresponding to these integers:
37, 80, 68, 70
① Open up a file
② Create a buffer
③ Use fread to read 4 individual bytes from that file
④ Print those out
- uint8_t : Unsigned Int of 8 bytes (always positive, takes 8 bits or 1 byte long)
Meaning, you can store a positive Integer with max number being 2^8-1.
If we use int buffer instead of uint8_t, we might not get the values we expect,
because int buffer[4] is 16 bytes long(an integer is 4 bytes long), whereas we're only going to read four of them.
<Writing to a File>
:basically the same as fread
fwrite(buffer, 1, 4, f);