Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ set(APP_SOURCES
"src/core/basics/InitializeVariable.cpp"
"src/core/basics/Operations.cpp"
"src/core/basics/ControlFlow.cpp"
"src/core/datatypes/Fundamental.cpp"
"src/core/datatypes/CArray.cpp"
"src/core/datatypes/CReferences.cpp"
"src/core/datatypes/CPointers.cpp"
"src/core/datatypes/CEnum.cpp"
"src/core/datatypes/CStruct.cpp"
"src/core/datatypes/CUnion.cpp"
"src/core/datatypes/TypeConVersions.cpp"
)

# Test files
Expand Down
28 changes: 28 additions & 0 deletions src/core/datatypes/CArray.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <iostream>

void arrayExamples()
{
std::cout << "\n--- Array Examples ---\n";

const int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; ++i)
{
std::cout << "arr[" << i << "] = " << arr[i] << "\n";
}

double matrix[2][3] = {{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}};
for (int i = 0; i < 2; ++i)
{
for (int j = 0; j < 3; ++j)
{
std::cout << "matrix[" << i << "][" << j << "] = " << matrix[i][j] << "\n";
}
}
}

struct CArray
{
CArray() { arrayExamples(); }
};

static CArray autoRunArray;
73 changes: 73 additions & 0 deletions src/core/datatypes/CEnum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <iostream>
#include <cstdint> // for uint8_t

using namespace std;
// A type defined in terms of other types

// *0. Define some enums
// Unscope enum
enum BasicEnum
{
enumratorA,
enumratorB,
enumratorC
};

// Scoped enum - enumrators are inside enum's scope
enum class ScopeEnumClass
{
enumratorA,
enumratorB,
enumratorC
};

// Scoped enum inside a namespace
namespace EnumNameSpace
{
enum class ScopeEnumClass
{
enumratorA,
enumratorB,
enumratorC
};
}

// Scoped enum with explicit base type
enum class ScopeEnumClassB : uint8_t
{
enumratorA = 0,
enumratorB = 1,
enumratorC = 2
};

void enums()
{
cout << "\n--- Enum Type Examples ---\n";
// *1. Using unscope enum
[[maybe_unused]] BasicEnum unscope_e = enumratorA;

// *2. Using scoped enum
[[maybe_unused]] ScopeEnumClass scope_e_c = ScopeEnumClass::enumratorA;

// *3. Using scoped enum namespace
[[maybe_unused]] EnumNameSpace::ScopeEnumClass scope_e_c_n = EnumNameSpace::ScopeEnumClass::enumratorA;

// *4. Using scoped enum with base type
[[maybe_unused]] ScopeEnumClassB st = ScopeEnumClassB::enumratorA;
}

// A struct that runs code when its object is created
struct CEnum
{
CEnum()
{
cout << "\n"
<< "\n"
<< "Compound type: Enum\n";

enums();
}
};

// All global and static objects are constructed before main() begins.
static CEnum autoRunInstance;
125 changes: 125 additions & 0 deletions src/core/datatypes/CPointers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include <iostream>
using namespace std;
// A type defined in terms of other types

// Simple function to demonstrate function pointers
int foo(int x)
{
cout << "x = " << x << endl;
return x;
}

void byPtr(int *x)
{
(*x)++;
cout << "x = " << *x << endl;
}

void byConstPtr(const int *const x)
{
// *x++; // error
cout << "x = " << *x << endl;
}

void byPtrConst(const int *x)
{
// *x++; // error
cout << "x = " << *x << endl;
}

void byConstPtrConst(const int *const x)
{
// *x++; // error
cout << "x = " << *x << endl;
}

static int global = 42;
int *returnPtr()
{
return &global; // the object must outlive the reference.
}

void pointers()
{
cout << "\n--- Pointers Type Examples ---\n";
int a = 10;
cout << "a = " << a << "\n";

// * 1. Pointer basics
const int *null_ptr = nullptr;
cout << "Address of nullptr (null_ptr): " << null_ptr << "\n";

// '&' gives the address of a variable
int *ptr_a = &a;
cout << "Address of a (&a): " << &a << "\n";
cout << "Value stored in pointer (ptr_a): " << ptr_a << "\n";

// '*' dereferences a pointer (accesses the value at that address)
cout << "Value of a via *ptr_a: " << *ptr_a << "\n";

// Change value of a through its pointer
*ptr_a = 2;
cout << "Value of a after *ptr_a = 2: " << a << "\n";

// * 2. Pointer to const
[[maybe_unused]] const int const_var = 100;
const int *ptr_const_var = &const_var;
// *ptr_const_var = 10; // cannot modify the value through pointer
cout << "Value of ptr_const_var " << *ptr_const_var << "\n";
ptr_const_var = &a; // can point somewhere else
cout << "Value of ptr_const_var " << *ptr_const_var << "\n";

// * 3. Const pointer
int *const const_ptr_a = &a;
*const_ptr_a = 10; // can change value
// const_ptr_a = nullptr; //cannot point to another variable

// * 4. Const pointer to const
[[maybe_unused]] const int *const const_ptr_const_var = &a;
// *const_ptr_const_var = 10; // cannot modify the value through pointer
// const_ptr_const_var = nullptr; //cannot point to another variable

// * 5. Pointer to pointer
int **ptr_ptr_a = new int *[10]; // dynamically allocate an array of 10 int*
ptr_ptr_a[0] = &a;
cout << "Value via pointer-to-pointer (*ptr_ptr_a[0]): " << *ptr_ptr_a[0] << "\n";
delete[] ptr_ptr_a; // always free heap memory

// * 6. Void pointer (generic pointer)
// void *void_ptr = static_cast<int*>(&a);
void *void_ptr = &a; // C-style pointer casting [cstyleCast]

cout << "Value via void pointer (after casting): " << *static_cast<int *>(void_ptr) << "\n";

// * 7. Function pointer
int (*fcn_ptr)(int) = &foo;
(*fcn_ptr)(5); // call via dereference
fcn_ptr(10); // call directly

// 8. Passing pointers
int in = 10;
byPtr(&in);
byConstPtr(&in);
byPtrConst(&in);
byConstPtrConst(&in);

// * 9. Return by ptr(address)
const int *b_ptr = returnPtr();
std::cout << "By ptr: " << *b_ptr << '\n';
}

// A struct that runs code when its object is created
struct CPointers
{
CPointers()
{
cout << "\n"
<< "\n"
<< "Compound type: Pointers\n";

pointers();
}
};

// All global and static objects are constructed before main() begins.
static CPointers autoRunInstance;
65 changes: 65 additions & 0 deletions src/core/datatypes/CReferences.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <iostream>
using namespace std;
// A type defined in terms of other types

void increment(int &x)
{
x += 1;
}

void incrementConst(const int &x)
{
// s cannot be modified here
// x += 1;
}

static int global = 42;
int &returnRef()
{
return global; // the object must outlive the reference.
}

void references()
{
cout << "\n--- References Type Examples ---\n";
int a = 10;
cout << "a = " << a << "\n";

// *1. Reference basics
// int &ref_error; // reference must be initialized
int &ref_a = a;

ref_a = 20; // modifies 'a', since ref is just an alias
cout << "ref_a =20, a = " << a << "\n"; // prints 20

// Cannot reseat: once 'ref' is bound to 'a', it cannot be bound to another variable
// int b = 30;
// ref = &b; invalid, would assign value instead of rebinding

// *2. Pass by reference
increment(a); // avoids making a copy
std::cout << "a after increment = " << a << "\n"; // prints 21

// *3. Pass by const reference
incrementConst(a);

// *4. Return by reference
int const &b = returnRef();
std::cout << "By reference: " << b << '\n';
}

// A struct that runs code when its object is created
struct CReferences
{
CReferences()
{
cout << "\n"
<< "\n"
<< "Compound type: References\n";

references();
}
};

// All global and static objects are constructed before main() begins.
static CReferences autoRunInstance;
86 changes: 86 additions & 0 deletions src/core/datatypes/CStruct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <iostream>
#include <string>

using namespace std;
// A type defined in terms of other types

// *0. Define a struct:
// structure alignment, padding, decreasing order of size
// public access
// In C, structs can only hold data members, not functions.
struct StructDataType
{
/* data */
double voltage{0.0}; // Default initialization
int id{0};
char status{'N'};
string label{"Unknown"};

/* function */
void print() const
{
cout << "Size of struct = " << sizeof(StructDataType) << " bytes" << endl;
cout << "Sensor " << id
<< " [" << label << "] "
<< "Voltage: " << voltage
<< " Status: " << status << endl;
}
};

void updateVoltageRef(StructDataType &data, double newV)
{
data.voltage = newV;
}

void updateVoltagePtr(StructDataType *data, double newV)
{
// (*data).voltage = newV;
if (data)
data->voltage = newV;
}

StructDataType makeSensor(int id, double v, const string &label)
{
return {v, id, 'N', label};
}

void structs()
{
cout << "\n--- Struct Type Examples ---\n";
// *1. Using struct
[[maybe_unused]] StructDataType data0; // default init
StructDataType data1{3.3, 1, 'N', "Temp1"};
StructDataType data2 = {6.3, 2, 'N', "Temp2"};

// *2. Access members
data1.print();
const StructDataType *ptr_data1 = &data1;
ptr_data1->print();

// *3. Passing by reference
updateVoltageRef(data2, 100);
data2.print();
// *4. Passing by pointer
updateVoltagePtr(&data2, 200);
data2.print();

// *5. Return a temporary struct
StructDataType s2 = makeSensor(2, 5.0, "Pressure");
s2.print();
}

// A struct that runs code when its object is created
struct CStruct
{
CStruct()
{
cout << "\n"
<< "\n"
<< "Compound type: Struct\n";

structs();
}
};

// All global and static objects are constructed before main() begins.
static CStruct autoRunInstance;
Loading