add Chapter01 examples
This commit is contained in:
19
Chapter01/README.md
Normal file
19
Chapter01/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Chapter01
|
||||
This folder contains examples in C and C++ from first chapter.
|
||||
|
||||
These are standalone examples that can be compiled by most compilers for x86_64 architecture.
|
||||
|
||||
You can explore the examples online in [Compiler Explorer](https://godbolt.org/).
|
||||
|
||||
The folder contains following examples:
|
||||
- ring_buffer.c
|
||||
- ring_buffer_type_erasure.c
|
||||
- ring_buffer_compile_time_generic.c
|
||||
- ring_buffer.cpp
|
||||
- compile_time_const.c
|
||||
- compile_time_const.cpp
|
||||
- compile_time_square_func.cpp
|
||||
- undefined_behavior.cpp
|
||||
- bloat.cpp
|
||||
- rtti.cpp
|
||||
- exceptions.cpp
|
||||
107
Chapter01/bloat.cpp
Normal file
107
Chapter01/bloat.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
|
||||
#if USE_TEMPLATES
|
||||
template <class T, std::size_t N> struct ring_buffer {
|
||||
std::array<T, N> arr;
|
||||
std::size_t write_idx = 0; // Index of the next element to write (push)
|
||||
std::size_t read_idx = 0; // Index of the next element to read (pop)
|
||||
std::size_t count = 0; // Number of elements in the buffer
|
||||
|
||||
void push(T t) {
|
||||
arr.at(write_idx) = t;
|
||||
write_idx = (write_idx + 1) % N;
|
||||
if (count < N) {
|
||||
count++;
|
||||
} else {
|
||||
// buffer is full, move forward read_idx
|
||||
read_idx = (read_idx + 1) % N;
|
||||
}
|
||||
}
|
||||
|
||||
T pop() {
|
||||
if (count == 0) {
|
||||
// Buffer is empty, return a default-constructed T.
|
||||
return T{};
|
||||
}
|
||||
T value = arr.at(read_idx);
|
||||
read_idx = (read_idx + 1) % N;
|
||||
--count;
|
||||
return value;
|
||||
}
|
||||
|
||||
bool is_empty() const { return count == 0; }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define N 10
|
||||
|
||||
struct ring_buffer_int {
|
||||
std::array<int, N> arr;
|
||||
std::size_t write_idx = 0; // Index of the next element to write (push)
|
||||
std::size_t read_idx = 0; // Index of the next element to read (pop)
|
||||
std::size_t count = 0; // Number of elements in the buffer
|
||||
|
||||
void push(int t) {
|
||||
arr.at(write_idx) = t;
|
||||
write_idx = (write_idx + 1) % N;
|
||||
++count;
|
||||
}
|
||||
|
||||
int pop() {
|
||||
if (count == 0) {
|
||||
// Buffer is empty, return a default-constructed T.
|
||||
return int{};
|
||||
}
|
||||
int value = arr.at(read_idx);
|
||||
read_idx = (read_idx + 1) % N;
|
||||
--count;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
struct ring_buffer_float {
|
||||
std::array<float, N> arr;
|
||||
std::size_t write_idx = 0; // Index of the next element to write (push)
|
||||
std::size_t read_idx = 0; // Index of the next element to read (pop)
|
||||
std::size_t count = 0; // Number of elements in the buffer
|
||||
|
||||
void push(float t) {
|
||||
arr.at(write_idx) = t;
|
||||
write_idx = (write_idx + 1) % N;
|
||||
++count;
|
||||
}
|
||||
|
||||
float pop() {
|
||||
if (count == 0) {
|
||||
// Buffer is empty, return a default-constructed T.
|
||||
return float{};
|
||||
}
|
||||
float value = arr.at(read_idx);
|
||||
read_idx = (read_idx + 1) % N;
|
||||
--count;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
#ifdef USE_TEMPLATES
|
||||
ring_buffer<int, 10> buffer1;
|
||||
ring_buffer<float, 10> buffer2;
|
||||
#else
|
||||
ring_buffer_int buffer1;
|
||||
ring_buffer_float buffer2;
|
||||
#endif
|
||||
for (int i = 0; i < 20; i++) {
|
||||
buffer1.push(i);
|
||||
buffer2.push(i + 0.2f);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
printf("%d, %.2f\r\n", buffer1.pop(), buffer2.pop());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
Chapter01/compile_time_const.c
Normal file
10
Chapter01/compile_time_const.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define VOLTAGE 3300
|
||||
#define CURRENT 1000
|
||||
|
||||
int main() {
|
||||
const float resistance = VOLTAGE / CURRENT;
|
||||
printf("resistance = %.2f\r\n", resistance);
|
||||
return 0;
|
||||
}
|
||||
10
Chapter01/compile_time_const.cpp
Normal file
10
Chapter01/compile_time_const.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <cstdio>
|
||||
|
||||
constexpr float voltage = 3300;
|
||||
constexpr float current = 1000;
|
||||
|
||||
int main() {
|
||||
const float resistance = voltage / current;
|
||||
printf("resistance = %.2f\r\n", resistance);
|
||||
return 0;
|
||||
}
|
||||
8
Chapter01/compile_time_square_func.cpp
Normal file
8
Chapter01/compile_time_square_func.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
constexpr int square(int a) {
|
||||
return a*a;
|
||||
}
|
||||
|
||||
int main() {
|
||||
constexpr int ret = square(2);
|
||||
return ret;
|
||||
}
|
||||
31
Chapter01/exceptions.cpp
Normal file
31
Chapter01/exceptions.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <cstdio>
|
||||
|
||||
struct A {
|
||||
A() { printf("A is created!\r\n"); }
|
||||
~A() { printf("A is destroyed!\r\n"); }
|
||||
};
|
||||
|
||||
struct B {
|
||||
B() { printf("B is created!\r\n"); }
|
||||
~B() { printf("B is destroyed!\r\n"); }
|
||||
};
|
||||
|
||||
void bar() {
|
||||
B b;
|
||||
throw 0;
|
||||
}
|
||||
|
||||
void foo() {
|
||||
A a;
|
||||
bar();
|
||||
A a1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
foo();
|
||||
} catch (int &p) {
|
||||
printf("Catching an exception!\r\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
50
Chapter01/ring_buffer.c
Normal file
50
Chapter01/ring_buffer.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define BUFFER_SIZE 5
|
||||
|
||||
typedef struct {
|
||||
int arr[BUFFER_SIZE]; // Array to store int values directly
|
||||
size_t write_idx; // Index of the next element to write (push)
|
||||
size_t read_idx; // Index of the next element to read (pop)
|
||||
size_t count; // Number of elements in the buffer
|
||||
} int_ring_buffer;
|
||||
|
||||
void int_ring_buffer_init(int_ring_buffer *rb) {
|
||||
rb->write_idx = 0;
|
||||
rb->read_idx = 0;
|
||||
rb->count = 0;
|
||||
}
|
||||
|
||||
void int_ring_buffer_push(int_ring_buffer *rb, int value) {
|
||||
rb->arr[rb->write_idx] = value;
|
||||
rb->write_idx = (rb->write_idx + 1) % BUFFER_SIZE;
|
||||
if (rb->count < BUFFER_SIZE) {
|
||||
rb->count++;
|
||||
} else {
|
||||
// Buffer is full, move read_idx forward
|
||||
rb->read_idx = (rb->read_idx + 1) % BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int int_ring_buffer_pop(int_ring_buffer *rb) {
|
||||
if (rb->count == 0) {
|
||||
return 0;
|
||||
}
|
||||
int value = rb->arr[rb->read_idx];
|
||||
rb->read_idx = (rb->read_idx + 1) % BUFFER_SIZE;
|
||||
rb->count--;
|
||||
return value;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int_ring_buffer rb;
|
||||
int_ring_buffer_init(&rb);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int_ring_buffer_push(&rb, i);
|
||||
}
|
||||
while (rb.count > 0) {
|
||||
int value = int_ring_buffer_pop(&rb);
|
||||
printf("%d\n", value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
48
Chapter01/ring_buffer.cpp
Normal file
48
Chapter01/ring_buffer.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
|
||||
template <class T, std::size_t N> struct ring_buffer {
|
||||
|
||||
std::array<T, N> arr;
|
||||
std::size_t write_idx = 0; // Index of the next element to write (push)
|
||||
std::size_t read_idx = 0; // Index of the next element to read (pop)
|
||||
std::size_t count = 0; // Number of elements in the buffer
|
||||
//
|
||||
void push(T t) {
|
||||
arr.at(write_idx) = t;
|
||||
write_idx = (write_idx + 1) % N;
|
||||
if (count < N) {
|
||||
count++;
|
||||
} else {
|
||||
// buffer is full, move forward read_idx
|
||||
read_idx = (read_idx + 1) % N;
|
||||
}
|
||||
}
|
||||
|
||||
T pop() {
|
||||
if (count == 0) {
|
||||
// Buffer is empty, return a default-constructed T.
|
||||
return T{};
|
||||
}
|
||||
T value = arr.at(read_idx);
|
||||
read_idx = (read_idx + 1) % N;
|
||||
--count;
|
||||
return value;
|
||||
}
|
||||
|
||||
bool is_empty() const { return count == 0; }
|
||||
};
|
||||
|
||||
int main() {
|
||||
ring_buffer<int, 5> rb;
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
rb.push(i);
|
||||
}
|
||||
|
||||
while (!rb.is_empty()) {
|
||||
printf("%d\n", rb.pop());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
53
Chapter01/ring_buffer_compile_time_generic.c
Normal file
53
Chapter01/ring_buffer_compile_time_generic.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
// Macro to declare ring buffer type and functions for a specific type and size
|
||||
#define DECLARE_RING_BUFFER(TYPE, SIZE) \
|
||||
typedef struct { \
|
||||
TYPE data[SIZE]; \
|
||||
size_t write_idx; \
|
||||
size_t read_idx; \
|
||||
size_t count; \
|
||||
} ring_buffer_##TYPE##_##SIZE; \
|
||||
void ring_buffer_init_##TYPE##_##SIZE(ring_buffer_##TYPE##_##SIZE *rb) { \
|
||||
rb->write_idx = 0; \
|
||||
rb->read_idx = 0; \
|
||||
rb->count = 0; \
|
||||
} \
|
||||
void ring_buffer_push_##TYPE##_##SIZE(ring_buffer_##TYPE##_##SIZE *rb, \
|
||||
TYPE value) { \
|
||||
rb->data[rb->write_idx] = value; \
|
||||
rb->write_idx = (rb->write_idx + 1) % SIZE; \
|
||||
if (rb->count < SIZE) { \
|
||||
rb->count++; \
|
||||
} else { \
|
||||
rb->read_idx = (rb->read_idx + 1) % SIZE; \
|
||||
} \
|
||||
} \
|
||||
int ring_buffer_pop_##TYPE##_##SIZE(ring_buffer_##TYPE##_##SIZE *rb, \
|
||||
TYPE *value) { \
|
||||
if (rb->count == 0) { \
|
||||
return 0; /* Buffer is empty */ \
|
||||
} \
|
||||
*value = rb->data[rb->read_idx]; \
|
||||
rb->read_idx = (rb->read_idx + 1) % SIZE; \
|
||||
rb->count--; \
|
||||
return 1; /* Success */ \
|
||||
} \
|
||||
|
||||
// Example usage with int type and size 5
|
||||
DECLARE_RING_BUFFER(int, 5) // Declare the ring buffer type and functions for ints
|
||||
//
|
||||
int main() {
|
||||
ring_buffer_int_5 rb;
|
||||
ring_buffer_init_int_5(&rb); // Initialize the ring buffer
|
||||
// Push values into the ring buffer
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ring_buffer_push_int_5(&rb, i);
|
||||
}
|
||||
// Pop values from the ring buffer and print them
|
||||
int value;
|
||||
while (ring_buffer_pop_int_5(&rb, &value)) {
|
||||
printf("%d\n", value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
54
Chapter01/ring_buffer_type_erasure.c
Normal file
54
Chapter01/ring_buffer_type_erasure.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUFFER_SIZE 20 // Total bytes available in the buffer
|
||||
//
|
||||
typedef struct {
|
||||
unsigned char data[BUFFER_SIZE]; // Array to store byte values
|
||||
size_t write_idx; // Index of the next byte to write
|
||||
size_t read_idx; // Index of the next byte to read
|
||||
size_t count; // Number of bytes currently used in the buffer
|
||||
size_t elem_size; // Size of each element in bytes
|
||||
} ring_buffer;
|
||||
|
||||
void ring_buffer_init(ring_buffer *rb, size_t elem_size) {
|
||||
rb->write_idx = 0;
|
||||
rb->read_idx = 0;
|
||||
rb->count = 0;
|
||||
rb->elem_size = elem_size;
|
||||
}
|
||||
|
||||
void ring_buffer_push(ring_buffer *rb, void *value) {
|
||||
if (rb->count + rb->elem_size <= BUFFER_SIZE) {
|
||||
rb->count += rb->elem_size;
|
||||
} else {
|
||||
rb->read_idx = (rb->read_idx + rb->elem_size) % BUFFER_SIZE;
|
||||
}
|
||||
memcpy(&rb->data[rb->write_idx], value, rb->elem_size);
|
||||
rb->write_idx = (rb->write_idx + rb->elem_size) % BUFFER_SIZE;
|
||||
}
|
||||
|
||||
int ring_buffer_pop(ring_buffer *rb, void *value) {
|
||||
if (rb->count < rb->elem_size) {
|
||||
// Not enough data to pop
|
||||
return 0;
|
||||
}
|
||||
memcpy(value, &rb->data[rb->read_idx], rb->elem_size);
|
||||
rb->read_idx = (rb->read_idx + rb->elem_size) % BUFFER_SIZE;
|
||||
rb->count -= rb->elem_size;
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
int main() {
|
||||
ring_buffer rb;
|
||||
ring_buffer_init(&rb, sizeof(int)); // Initialize buffer for int values
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int val = i;
|
||||
ring_buffer_push(&rb, &val);
|
||||
}
|
||||
int pop_value;
|
||||
while (ring_buffer_pop(&rb, &pop_value)) {
|
||||
printf("%d\n", pop_value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
29
Chapter01/rtti.cpp
Normal file
29
Chapter01/rtti.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <cstdio>
|
||||
|
||||
struct Base {
|
||||
virtual void print() {
|
||||
printf("Base\r\n");
|
||||
}
|
||||
};
|
||||
|
||||
struct Derived : public Base {
|
||||
void print() override {
|
||||
printf("Derived\r\n");
|
||||
}
|
||||
};
|
||||
|
||||
void printer(Base &base) {
|
||||
base.print();
|
||||
|
||||
if(Derived *derived = dynamic_cast<Derived*>(&base); derived!=nullptr) {
|
||||
printf("We found Base using RTTI!\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Base base;
|
||||
Derived derived;
|
||||
printer(base);
|
||||
printer(derived);
|
||||
return 0;
|
||||
}
|
||||
16
Chapter01/undefined_behavior.cpp
Normal file
16
Chapter01/undefined_behavior.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
int foo(int x) {
|
||||
int y = x + 1;
|
||||
return y > x;
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (foo(std::numeric_limits<int>::max())) {
|
||||
printf("X is larger than X + 1\r\n");
|
||||
} else {
|
||||
printf("X is NOT larger than X + 1. Oh nooo !\r\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user