ctut/README.md

208 lines
7.1 KiB
Markdown
Raw Permalink Normal View History

2019-03-14 04:13:46 +00:00
# C Musings
Some musings on C-family languages, by Nora for Ania!
## History of the C Family
In the early days of computing, MIT, General Electric, and Bell Labs created MULITCS,
the Multiplexed Information and Computing Service. This operating system introduced
many ideas that are commonplace today. It also kind of sucked, and the project fell apart.
From the ashes rose UNIX, an operating system which, like all OSes at the time, was written
entirely in non-portable assembly code for a specific machine, the DEC PDP-10. It used
an interpreted language called B for some non-performance-critical code that needed to be
easy to modify.
As it became popular in the early 1970s, Dennis Ritchie, Brian Kernighan, and others decided
to port it to a number of other computers. To ease this task, they invented a computer language
that abstracted over the specifics of machine language of any particular computer, but was
close enough to the model exposed by most machines that, with a little machine-specific
assembly code, the only thing that had to be ported to each new machine was the compiler.
The compiler is a "simple" piece of code that translates the C code to machine-specific
instructions. Nowadays, compilers are extremely complex, as they perform optimization as
well as simple compilation.
Because C is so low level, it is entirely _imperative_. All of its high-level features,
such as structures and function pointers, come from the way the machine works, not from
any magic (runtime) applied by the compiler.
### C++
C++ is an invention of Bjarne Stroustroup, a brilliant computer scientist who decided to
apply object oriented principles to C. The result was an absolute mess of a language
that is nonetheless very powerful and, as time goes on, is becoming more and more safe
and easy to use.
It has somewhat more of a runtime then C, and the compiler does a lot more work, including
permitting type-system level templating.
### C#
C# is Microsoft's answer to Java. It's really similar to Java and has very little to do
with C.
## The C Programming Language
That's the name of a [terrible book](https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628)
that you shouldn't read. I did, it blew my mind and I learned nothing.
Anyway, what defines the C language?
C is **statically typed**. That means, like Java and unlike Python, a variable has to
keep the same type throughout the program:
```c
int a = 24;
a = "Hello, world!"; // Compiler error
```
C is **weakly typed**. That means, unlike both Java and Python, C will do it's _very best_
to do _something_ even when you give it types that make little sense, _based on the way
the PDP-10 would have done it in its CPU_.
```c
int a = 25;
char b = 'b';
a + b; // This is an integer of the value 25 plus the integer value of the letter b.
```
C is **procedural**. Its primary abstraction is the procedure call, or function call.
This is as opposed to object-oriented languages, for example.
Finally, C is **memory unsafe**. Because it has no runtime and gives you access to the
very lowest level of the machine (or at least does a good job of pretending), you can
do silly things without anyone stopping you.
```c
char[] c = "Hello, world!"; // A string is an array of characters.
char nonsense = c[134]; // This will cause a problem, probably.
```
This code won't throw an `IndexOutOfBounds` exception or anything; there's no runtime
to check that. Instead, the compiler will very earnestly try to write code that does this;
it will get the address of the start of the array `c`, compute the memory address 134 bytes
later, and try to see what's there. This will certainly be gibberish and might cause the
operating system to kill your program.
2019-03-14 03:51:04 +00:00
2019-03-14 04:29:52 +00:00
# Setting Up a Development Environment
To develop C, you need a _compiler_, and it's nice to have a _build system_. I'll assume
you're on Ubuntu; to install GCC, the GNU Compiler Collection, and make, a build system,
on Ubuntu, run:
```bash
sudo apt install gcc make
```
Now make a directory to work in and open up a file. I'm going to call it `00-helloworld.c`.
Into that file, type:
```c
#include <stdio.h>
int main(int argc, char** argv) {
printf("Hello, world!\n");
}
```
(I'll explain it all in a sec!)
Now, in the terminal, in that folder, type:
```bash
# GCC, please compile the code in 00-helloworld.c
# and write the executable out to 00-helloworld.64
gcc 00-helloworld.c -o 00-helloworld.64
```
This should print out "Hello, world!" in your terminal. Let's dissect that.
```c
#include <stdio.h>
```
Beginning with `#` means that this is a preprocessor directive, telling the compiler
to look up and include a file called `stdio.h` in the standard search path (because of
the `<` and `>`, as opposed to `"` and `"` which mean look in the current directory)
and include its text here.
That file defines, among other things, the function `printf` that is used later.
```c
int main(int argc, char** argv) {
```
This is the definition of the magic function `main`, which is run when the program starts.
It returns an `int`, which should be zero for success or anything else for failure, and
takes the number of command line arguments `argc` and an array of arrays of characters
(an array of strings) `argv`. `c` stands for "count" and `v` for "vector" in this case.
```c
printf("Hello, world!\n");
```
This calls the `printf` function, which `print`s a `f`ormatted string, although we're
2019-03-14 04:43:31 +00:00
not using any of the formatting options here. The `\n` is a standin for the newline
character.
2019-03-14 04:29:52 +00:00
2019-03-14 04:43:31 +00:00
Congratulations! This is your first C program, and demonstrates that your development
environment is working.
2019-03-14 04:29:52 +00:00
2019-03-14 04:43:31 +00:00
# Pointers and Looping
In a file called `01-arguments.c`, write:
```c
#include <stdio.h>
int main(int argc, char** argv) {
printf("Given %d arguments.\n", argc);
int index = 0;
while (index < argc) {
printf("Argument %d: %s\n", index, argv[index]);
index = index + 1;
}
}
```
This is pretty similar, but has a few more complications.
```c
printf("Given %d arguments.\n", argc);
```
Here, `%d` means "replace this placeholder with the first argument after the string,
which should be an integer". `d` stands for digit.
```c
int index = 0;
```
This is the declaration of a variable "index", which will be used to keep track of our
place in the array.
```c
while (index < argc) {
```
This means run the following code until the `index` variable becomes greater than or equal
to `argc`, the number of command line arguments.
```c
printf("Argument %d: %s\n", index, argv[index]);
```
This line has a few new things in it; `%s` is the placeholder for strings, and `argv[index]`
is taking looking at the `index`th element in `argv`, an array of strings.
Or, you can look at it a different way: `argv` is a `char**`, a `*` (pointer) to a `*` (pointer)
to a `char`. A "pointer" is simply an **unsigned integer** which represents, instead of a
number, a location in memory.
So, `char** argv` is the memory location of the first element in a list of pointers, each
of which is the memory location of the first element in a list of `char`s. Those lists of
`char`s all end with `\0`, the 0 byte, and represent the text of the program's command
line arguments.