Lec 01: C
1. Three qualities
- Correctness, or whether our code works correctly, as intended.
- Design, or a subjective measure of how well-written our code is, based on how efficient it is and how elegant or logically readable it is, without unnecessary repetition.
- Style, or how aesthetically formatted our code is, in terms of consistent indentation and other placement of symbols. Differences in style don't affect the correctness or meaning of our code, but affect how readable it is visually.
2. Compiling
2.1. Source code v.s. Machine code
We'll compile our code before we can run it. Computer can only understand binary, which is also used to represent instructions like print something to the screen.
Our source code has been written in characters we can read,(i.e., hello.c
) but it need to be compiled: convert to machine code, patterns of zeros and ones that our computer can directly understand.
E.g., hello.c
of source code:
2.2. Compiler
But how can we convert source code to machine code, there we need is a program called compiler, which will take source code as input and produce machine code as output.
For example, in CS50 IDE, the compiler program name is called make, when we type make hello
in the terminal of CS50 IDE, it'll automatically find our hello.c
file as source code of input, and then convert it to machine code which is actually a executable program called hello
, and it's the parameter we input.
There will be some output to tell you whether your compiling is successful, if there's no error messages in yellow or red, it's compiled successful.
3. Functions and arguments
That's the same ideas we've explored in 0x00 Scratch
.
We've known that a function is an instance of algorithms, which has an input and an output, where output is produced by its algorithm.
We can imagine the functions as small actions or verbs that we can use in our program to do something, which we called abstraction we'll detail it later.
3.1. Arguments
The input of functions we called arguments.
E.g., the function printf
(with the f
standing for "formatted" text), we pass the arguments with parentheses, as in printf("Hello World!");
, the double quotes indicate that we want to print out the letters hello world
literally, and the semicolon at the end indicates the end of our line of code.
3.2. Outputs
Functions can also have two kinds of outputs:
- side effects, such as something printed to screen, or play sound.
- return value, a value that is passed back to our program that we can use or store for later. (e.g.,
add(num1, num2)
function, which will return the result of addition back to us.)
3.3. Library
How can we use the functions we've already written, or the functions the others written? We'll use a library, which is a set of code already written.
For example, the cs50
library we already used includes some basic , simple functions that we can use right away.(E,g., get_string
)
Before we can use the functions of library, we need to declare it, that is telling the compiler to include the Library we wanna used.
3.4. Escape sequence
What is escape sequence is some text that represents some other text probably hard to type.
Like \n
in printf("hello, world\n");
, which represent a newline character.
4. main, header file
4.1. main function
Main function is the entrance of the whole program, we'll learn more about it later, for now we'll simply use this to start our program.
4.2. Header files
Header files that end with .h
refer to some other set of code, like a library, that we can then use in our program.
We include them with lines like #include <stdio.h>
, which stdio.h
standing for the standard input/output library, which contains printf
function.
5. Types, format codes
5.1. Types
There are many data types we can use for our variables, which indicate to the computer what type of data they represent.
bool
, a Boolean expression of eithertrue
orfalse
char
, a singleASCII
character likea
or2
double
, a floating-point value with more digits than afloat
float
, a floating-point value, or a real-number with a decimal valueint
, integers up to a certain size, or number of bitslong
, integers with more bits, so they can count higher than anint
string
, a string of characters
5.2. Format codes
For printf
, there are also different placeholders for each type:
%c
for chars%f
for floats, doubles%i
, for ints%li
, for longs%s
, for strings
6. Operators, limitations, truncation
6.1. Operators
There are several mathematical operators we can use too:
-
+
for addition -
-
for subtracation -
*
for multiplication -
/
for division -
%
for remainder
6.2. Limitations
When we get an integer with get_int
function, it'll denied our input if it more than 2 billion, or less than minus 2 billion. That's because all the types have its limitations of memory.
In this case, the limitation of int
is from -2^31^ to 2^31^ - 1 cause like on many computer systems, an int
is 32 bits, which can only contain 2^32^ numbers(negative 2^31^ number, positive 2^31^ - 1 numbers and zero).
6.3. Truncation
Since each type has its limitation, does these limitations effect the mathematical operation?
If we divide an integer by another one, then save the result to a float number, what would happen? The answer is truncation, with the value after the decimal point lost. Even though result
is a double
, the value we're storing in it is already an integer.
To fix this, we cast, or convert, out integers to floats before we divide them.
Then the result will be a float as we expect, actually we can cast only one of x
or y
and get a float as well.
7. Variables, syntactic suger
7.1. Variables
In C, we would write type name = value;
to create a variable and give it some value.
7.2. Syntactic suger
What is syntactic sugar is shorthand expressions for the same functionality.
E.g., we can increase the value of a variable with result = result + 1;
, we also could equivalently say result += 1
, we even could just write it as result++
. We can learn this through looking at the documentation or other references online.
8. Conditions
We can use conditions in C, that is if
, else if
, else
blocks, with:
And we could notice that in C we use {
and }
(as well as indentation) to indicate how lines of code should be nested.
We use two vertical bar ||
to indicate a logical or, two ampersands &&
to indicate a logical and. Then two equal signs ==
to compare two values whether it's equal.(Essentially a character is a value, that with two single quotes surrounding it)
9. Boolean expressions, loops
9.1. Boolean expressions
Boolean expressions is an expression with the value either true
value or false
value.
Boolean expressions controls the loops keep running or not.
9.2. Loops
Loops requires a condition, and it will check the condition whether it's true, if it is, Loop will run once, and then check again.
10. Abstraction
We can reuse out designs, like abstract it to a function. That will make our code more readable.
By using abstraction, we could concentrate on more high-level, and reduce repetition of codes.
11. Memory, imprecision, and overflow
11.1. Memory
Our computer has memory, in hardware chips called RAM, random-access memory. Our programs use RAM to store data while they're running, BUT that memory is finite.
11.2. Imprecision
Because RAM is finite, it will cause imprecision:
It turns out that is called float-point imprecision, where we don't have enough bits to store all possible values. With a finite number of bits for a float
, we can't represent all possible real numbers (of which there are an infinite number of), so the computer has to store the closest value it can.
11.3. Overflow
If we only have three bits and need to count higher than seven (111
), we add another bit to get eight, 1000
. But if we only have three bits available, we won't have a place for extra 1
. It will disappear and we will be back at 000
. This problem is called integer overflow, where an integer can only be so big before it runs out of bits.