Skip to content

Commit 756f532

Browse files
committed
Rename folders to put an index on them to sort them a bit better in editor. Also some minor changes.
1 parent e04667a commit 756f532

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3144
-3082
lines changed
File renamed without changes.

c_and_cpp_background/index.md 02_c_and_cpp_background/index.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ This section talks about C and C++. It describes its history, standards and prov
1010

1111
The C [^1] programming language was developed as part of Unix [^2] by Dennis Ritchie and Ken Thompson.
1212

13-
Unix started life on the PDP-7 microcomputer. This version was written in assembly language. The OS was then ported to the PDP-11 architecture, also in assembly.
13+
Unix started life on the PDP-7 microcomputer and was originally written in assembly language. The OS was then ported to the PDP-11 architecture, also in assembly.
1414

15-
Ritchie developed C in 1972 as a higher level language and compiler for writing Unix software than pure assembly. The language provided constructs such as static types, loops, conditionals, expressions etc and the compiler produced machine code which was almost as efficient as hand written assembly. Over time much of Unix itself, including much of the kernel was rewritten in C which in turn aided portability.
15+
Ritchie developed C in 1972 as a higher level language and compiler for writing Unix software in a more abstract way than pure assembly. The language provided constructs such as static types, loops, conditionals, expressions etc and the compiler produced machine code which was almost as efficient as hand written assembly. Over time much of Unix itself, including much of the kernel was rewritten in C which in turn aided portability.
1616

17-
The compiler was also a bundled component of Unix, so Unix users could develop their own software using the language.
17+
The compiler was also a bundled component of Unix, so Unix users could develop their own software using the language. Thus C became a popular way of developing Unix software.
1818

1919
[^1] C was called C because it was influenced by a language called B developed by Thompson as a simplified version of BCPL.
2020

@@ -46,18 +46,18 @@ C++ has also become formalised standards with C++98, C++03, C++11 and so on.
4646

4747
[^3] Simula is a language that allowed concepts such as objects, classes and inheritance to be expressed in code and as its name suggests was created for running simulations. However it was considered too slow for systems programming and so something that combined speed of C with object oriented concepts was highly desirable.
4848

49-
#### Modern C++
49+
### Modern C++
5050

5151
C++11 onwards is a distinctly different beast from earlier iterations and strives to add functionality that if used correctly can eliminate a lot of issues that will be discussed later on:
5252

53-
* Scoped and shared pointers
54-
* auto keyword
53+
* Unique and shared pointers
54+
* `auto` keyword
5555
* move semantics \(i.e. moving data ownership of data from one variable to another\)
5656
* rvalue references
5757
* perfect forwarding
58-
* nullptr explicit type
58+
* `nullptr_t` and `nullptr` explicit type
5959

60-
However it is worth noting that since many of these things are late additions to C++. Things like move semantics must be explicitly used and have implications that are not an issue for Rust where they have been part of the language since early on.
60+
However it is worth noting that since many of these things are late additions to C++. Things like move semantics must be explicitly used and have complexity as we shall see.
6161

6262
### The relationship between C and C++
6363

@@ -91,15 +91,15 @@ These are the major revisions of C and C++
9191
| 1978 | K&R C | C as defined in "The C Programming Language" book by Kernighan & Ritchie |
9292
| 1979 | C with classes -> C++ | Bjarne Stroustrops |
9393
| 1989 | C89 \(ANSI X3.159-1989\) | C is standardized as ANSI C, or C89. C90 \(ISO/IEC 9899:1990\) is the ISO ratified version of this same standard. |
94+
| 1987 | GNU C Compiler \(GCC\) | An open source C compiler that was quickly adopted by developers and became the defacto compiler for most Unix / Linux systems. Acronym `GCC` was rebranded as GNU Compiler Chain since the project encapsulated many other languages including C++, Objective-C, Ada, Fortran etc. that had individual compiler front-ends but shared the code generating backend. |
9495
| 1995 | C95 \(ISO/IEC 9899/AMD1:1995\) | Wide character support, digraphs, new macros, and some other minor changes. |
9596
| 1998 | C++98 \(ISO/IEC 14882:1998\) | C++ is standardized for the first time. |
9697
| 1999 | C99 \(ISO/IEC 9899:1999\) | Single line \(//\) comments, mixing declarations with code, new intrinsic types, inlining, new headers, variable length arrays |
9798
| 2003 | C++03 \(ISO/IEC 14882:2003\) | Primarily a defect revision, addressing various defects in the specification. |
98-
| 2011 | C++11 \(ISO/IEC 14882:2011\) | A major revision that introduces type inference \(auto\), range based loops, lambdas, strongly typed enums, a nullptr constant, struct initialization. Improved unicode char16\_t, char32\_t, u, U and u8 string literals. |
99+
| 2003 | LLVM | Similar to GCC, a compiler and toolchain that started predominantly to support compiling C and C++ via the Clang compiler with many backends for generating machine code across across many platforms. The toolchain is also used by the Rust compiler. |
100+
| 2011 | C++11 \(ISO/IEC 14882:2011\) | A major revision that introduces type inference \(auto\), range based loops, lambdas, strongly typed enums, a nullptr constant, struct initialization. Improved Unicode char16\_t, char32\_t, u, U and u8 string literals. |
99101
| 2011 | C11 \(ISO/IEC 9899:2011\) | Multi-threading support. Improved unicode char16\_t, char32\_t, u, U and u8 string literals. Other minor changes |
100102
| 2014 | C++14 \(ISO/IEC 14882:2014\) | A major revision that introduces auto return types, variable templates, digit separators \(1'000'000\), generic lambdas, lambda capture expressions, deprecated attribute.
101103
| 2017 | C++17 \(ISO/IEC 14882:2017\) | A major revision that introduces a number of enhancements but notably a filesystem library, `string_view` and `option` types and `UTF-8` strings |
102104

103105
In a sense C++ is converging with Rust since many of the enhancements which have gone into the language have the potential to make code safer and more efficient.
104-
105-
However C++ is still an unsafe by default language. For example C++17 introduces `string_view` but it does not care if the string exists or not when it is called and it is the programmer's responsibility to ensure it does. Whereas a `&str` slice in Rust is lifetime checked by the compiler.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+151-151
Original file line numberDiff line numberDiff line change
@@ -1,152 +1,152 @@
1-
# Porting Code
2-
3-
Before starting, the assumption at this point is you *need* to port code. If you're not sure you do to port code, then maybe you don't. After all, if your C/C++ code works fine, then why change it?
4-
5-
TODO This section will provide a more real world C/C++ example and port it to the equivalent Rust
6-
7-
## Automation tools
8-
9-
### C2Rust
10-
11-
The [C2Rust project](https://github.com/immunant/c2rust) is developing a tool that translates C to semantically equivalent Rust.
12-
13-
There is an online demo of it working [here](https://c2rust.com/).
14-
15-
As C is unsafe by default, it means the Rust equivalent is also unsafe by default, but it can be useful as a starting point for converting code.
16-
17-
### Corrode
18-
19-
[Corrode](https://github.com/jameysharp/corrode) is a command-line tool that can partially convert C into Rust. At the very least it may spare you some drudgery ensuring the functionality is as close to the original as possible.
20-
21-
Corrode will take a C file, e.g. `somefile.c` plus any arguments from `gcc` and produces a `somefile.rs` which is the equivalent code in Rust.
22-
23-
It works by parsing the C code into an abstract syntax tree and then generating Rust from that.
24-
25-
Interestingly Corrode is written in Haskell and more interestingly is written as a [literate Haskell source](https://github.com/jameysharp/corrode/blob/master/src/Language/Rust/Corrode/C.md) - the code is a markdown document interspersed with Haskell.
26-
27-
### Bindgen
28-
29-
[Bindgen](https://github.com/servo/rust-bindgen) is a tool for generating FFI interfaces for Rust from existing C and C++ header files. You might find this beneficial if you're porting code from C / C++, or writing a new component that must work with an existing code base.
30-
31-
Bindgen requires that you preinstall the Clang C++ compiler in order to parse code into a structure it can digest.
32-
33-
The readme documentation on the site link provides more information on installing and using the tool.
34-
35-
### CBindgen
36-
37-
[CBindgen](https://github.com/eqrion/cbindgen) works in the opposite direction of bindgen - it produces C header files from Rust structures and functions.
38-
39-
So if you have Rust code that you wish to call from C, then you can generate the appropriate header files that enable you to do this.
40-
41-
The headers can be produced from the command line like so:
42-
43-
```
44-
cargo install cbindgen
45-
cbindgen -o bindings.h
46-
```
47-
48-
Alternatively you can create a `build.rs` that automatically does this when you build your crate:
49-
50-
```rust
51-
extern crate cbindgen;
52-
53-
use std::env;
54-
55-
fn main() {
56-
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
57-
58-
cbindgen::Builder::new()
59-
.with_crate(crate_dir)
60-
.generate()
61-
.expect("Unable to generate bindings")
62-
.write_to_file("bindings.h");
63-
}
64-
```
65-
66-
A `cbindgen.toml` allows you to configure things that go into the header file. See the site link for more information.
67-
68-
69-
## Experiences
70-
71-
A number of websites offer insights of the porting process from C to Rust
72-
73-
1. [Porting Zopfli from C to Rust](https://github.com/carols10cents/rust-out-your-c-talk). Zopfli is a library that performs good but slow deflate algorithm. It produces smaller compressed files than zlib while still remaining compatible with it.
74-
2. TODO
75-
76-
# Tips
77-
78-
## Use references wherever you can
79-
80-
TODO references are equivalent to C++ references or to pointers in C. Passing by reference is an efficient way of passing any object greater than 64-bits in size into a function without relinquishing ownership. In some cases, it is even a good idea to return by reference since the caller can always clone the object if they need to, and more often than not they can just use the reference providing the lifetimes allow for it.
81-
82-
TODO you do not need to use references on intrinstic types such as integers, bools etc. and there is no point unless you intend for them to be mutable and change.
83-
84-
## Move semantics
85-
86-
C and C++ default to copy on assign. Unless you explicitly implement a move constructor on objects, the default is copy. Copying is dangerous because it allows two data structures to potentially point to the same data, e.g. a raw file handle. Even if code implements a move constructor, the compiler will not care if you reference the old
87-
object so you are required to put the object into a valid but safe state.
88-
89-
Rust by default will move on assign unless the type implements a `Copy` trait. Only simple primitives or structs comprised of simple primitives can implement or derive the `Copy` trait.
90-
91-
```rust
92-
let x = 100;
93-
let y = x; // This is a copy
94-
println!("x = {}", x);
95-
96-
let x = "Hello world".to_string();
97-
let y = x; // This is a move
98-
println!("x = {}", x); // compile error
99-
```
100-
101-
And unlike C++, you CANNOT access the old object once you have assigned the value to a new one. The compiler will generate an error if you try.
102-
103-
If you need to copy data in Rust you must implement / derive the `Clone` trait which allows you to explicitly invoke `.clone()` to make a copy of an object:
104-
105-
```rust
106-
let x = "Hello world".to_string();
107-
let y = x.clone();
108-
println!("x = {}", x);
109-
110-
#[derive(Clone)]
111-
struct MyData {
112-
name: String;
113-
}
114-
///...
115-
let x = MyData { name: "Fred".to_string() };
116-
let y = x.clone();
117-
```
118-
119-
## Use modules to naturally arrange your source code
120-
121-
TODO
122-
123-
## Using composition and traits
124-
125-
TODO Rust does not allow you to inherit one struct from another. The manner of overcoming this.
126-
127-
## Using Cargo.toml to create your build profiles
128-
129-
## Use Rust naming conventions and formatting
130-
131-
C and C++ have never had
132-
133-
# Foreign Function Interface
134-
135-
TODO for now read the [FFI omnibus](http://jakegoulding.com/rust-ffi-omnibus/).
136-
137-
## Leaving function names unmangled
138-
139-
TODO attribute no_mangle
140-
141-
## libc
142-
143-
TODO Rust provides a crate with bindings for C library functions. If you find yourself receiving a pointer allocated with malloc you could free it with the corresponding call to free() via the bindings.
144-
145-
TODO add the following to your `Cargo.toml`
146-
147-
```
148-
[dependencies]
149-
libc = "*"
150-
```
151-
1+
# Porting Code
2+
3+
Before starting, the assumption at this point is you *need* to port code. If you're not sure you do to port code, then maybe you don't. After all, if your C/C++ code works fine, then why change it?
4+
5+
TODO This section will provide a more real world C/C++ example and port it to the equivalent Rust
6+
7+
## Automation tools
8+
9+
### C2Rust
10+
11+
The [C2Rust project](https://github.com/immunant/c2rust) is developing a tool that translates C to semantically equivalent Rust.
12+
13+
There is an online demo of it working [here](https://c2rust.com/).
14+
15+
As C is unsafe by default, it means the Rust equivalent is also unsafe by default, but it can be useful as a starting point for converting code.
16+
17+
### Corrode
18+
19+
[Corrode](https://github.com/jameysharp/corrode) is a command-line tool that can partially convert C into Rust. At the very least it may spare you some drudgery ensuring the functionality is as close to the original as possible.
20+
21+
Corrode will take a C file, e.g. `somefile.c` plus any arguments from `gcc` and produces a `somefile.rs` which is the equivalent code in Rust.
22+
23+
It works by parsing the C code into an abstract syntax tree and then generating Rust from that.
24+
25+
Interestingly Corrode is written in Haskell and more interestingly is written as a [literate Haskell source](https://github.com/jameysharp/corrode/blob/master/src/Language/Rust/Corrode/C.md) - the code is a markdown document interspersed with Haskell.
26+
27+
### Bindgen
28+
29+
[Bindgen](https://github.com/servo/rust-bindgen) is a tool for generating FFI interfaces for Rust from existing C and C++ header files. You might find this beneficial if you're porting code from C / C++, or writing a new component that must work with an existing code base.
30+
31+
Bindgen requires that you preinstall the Clang C++ compiler in order to parse code into a structure it can digest.
32+
33+
The readme documentation on the site link provides more information on installing and using the tool.
34+
35+
### CBindgen
36+
37+
[CBindgen](https://github.com/eqrion/cbindgen) works in the opposite direction of bindgen - it produces C header files from Rust structures and functions.
38+
39+
So if you have Rust code that you wish to call from C, then you can generate the appropriate header files that enable you to do this.
40+
41+
The headers can be produced from the command line like so:
42+
43+
```
44+
cargo install cbindgen
45+
cbindgen -o bindings.h
46+
```
47+
48+
Alternatively you can create a `build.rs` that automatically does this when you build your crate:
49+
50+
```rust
51+
extern crate cbindgen;
52+
53+
use std::env;
54+
55+
fn main() {
56+
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
57+
58+
cbindgen::Builder::new()
59+
.with_crate(crate_dir)
60+
.generate()
61+
.expect("Unable to generate bindings")
62+
.write_to_file("bindings.h");
63+
}
64+
```
65+
66+
A `cbindgen.toml` allows you to configure things that go into the header file. See the site link for more information.
67+
68+
69+
## Experiences
70+
71+
A number of websites offer insights of the porting process from C to Rust
72+
73+
1. [Porting Zopfli from C to Rust](https://github.com/carols10cents/rust-out-your-c-talk). Zopfli is a library that performs good but slow deflate algorithm. It produces smaller compressed files than zlib while still remaining compatible with it.
74+
2. TODO
75+
76+
# Tips
77+
78+
## Use references wherever you can
79+
80+
TODO references are equivalent to C++ references or to pointers in C. Passing by reference is an efficient way of passing any object greater than 64-bits in size into a function without relinquishing ownership. In some cases, it is even a good idea to return by reference since the caller can always clone the object if they need to, and more often than not they can just use the reference providing the lifetimes allow for it.
81+
82+
TODO you do not need to use references on intrinstic types such as integers, bools etc. and there is no point unless you intend for them to be mutable and change.
83+
84+
## Move semantics
85+
86+
C and C++ default to copy on assign. Unless you explicitly implement a move constructor on objects, the default is copy. Copying is dangerous because it allows two data structures to potentially point to the same data, e.g. a raw file handle. Even if code implements a move constructor, the compiler will not care if you reference the old
87+
object so you are required to put the object into a valid but safe state.
88+
89+
Rust by default will move on assign unless the type implements a `Copy` trait. Only simple primitives or structs comprised of simple primitives can implement or derive the `Copy` trait.
90+
91+
```rust
92+
let x = 100;
93+
let y = x; // This is a copy
94+
println!("x = {}", x);
95+
96+
let x = "Hello world".to_string();
97+
let y = x; // This is a move
98+
println!("x = {}", x); // compile error
99+
```
100+
101+
And unlike C++, you CANNOT access the old object once you have assigned the value to a new one. The compiler will generate an error if you try.
102+
103+
If you need to copy data in Rust you must implement / derive the `Clone` trait which allows you to explicitly invoke `.clone()` to make a copy of an object:
104+
105+
```rust
106+
let x = "Hello world".to_string();
107+
let y = x.clone();
108+
println!("x = {}", x);
109+
110+
#[derive(Clone)]
111+
struct MyData {
112+
name: String;
113+
}
114+
///...
115+
let x = MyData { name: "Fred".to_string() };
116+
let y = x.clone();
117+
```
118+
119+
## Use modules to naturally arrange your source code
120+
121+
TODO
122+
123+
## Using composition and traits
124+
125+
TODO Rust does not allow you to inherit one struct from another. The manner of overcoming this.
126+
127+
## Using Cargo.toml to create your build profiles
128+
129+
## Use Rust naming conventions and formatting
130+
131+
C and C++ have never had
132+
133+
# Foreign Function Interface
134+
135+
TODO for now read the [FFI omnibus](http://jakegoulding.com/rust-ffi-omnibus/).
136+
137+
## Leaving function names unmangled
138+
139+
TODO attribute no_mangle
140+
141+
## libc
142+
143+
TODO Rust provides a crate with bindings for C library functions. If you find yourself receiving a pointer allocated with malloc you could free it with the corresponding call to free() via the bindings.
144+
145+
TODO add the following to your `Cargo.toml`
146+
147+
```
148+
[dependencies]
149+
libc = "*"
150+
```
151+
152152
TODO example of using libc
File renamed without changes.

0 commit comments

Comments
 (0)