add Chapter01 examples

This commit is contained in:
Amar Mahmutbegovic
2024-04-27 20:43:40 +02:00
parent fb4983465f
commit de6d74e093
12 changed files with 435 additions and 0 deletions

19
Chapter01/README.md Normal file
View 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
View 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;
}

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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;
}

View 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;
}

View 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
View 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;
}

View 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;
}