====== C and C++ ======
===== C declerations =====
A c decleration can be read by following this rule and knowing about precedence.
Go left when you can and right when you must.
char *(*(**foo [][8])())[];
foo is an array to an array of 8 pointers to poiners to a function that returns
a pointer to an array of pointers to char
===== C++ Interview questions =====
I was given a pop quiz by a non-tech interviewer once on c++. Here was his questions:
- What is the name of an invalid pointer?
- Weird question and I don't think it's right. Answer he was looking for was null.
- What is the difference between a struct and a class?
- What is the keyword to deallocate memory? Lol
- When using a new keyword where is the memory stored, stack or heap? Heap OBVI.
- If a program crashes and you have a core dump and debugger, what is the first thing you do?
- Look at a backtrace, see where the program crashed, look at what the variable were.
===== General C++ =====
Principles of C++: (([[https://www.grimm-jaud.de/images/stories/pdfs/c%2B%2B11_AnOverview.pdf|Rainer Grimm's C++ 11 overview]]))
* Trust the programmer.
* You don't have to pay for something you don't need.
* Don't break existing code.
* Prefer compile time errors over run time errors.
===== Differences Between C and C++ =====
Here are some differences I have come across between C and C++. This stuff is
interesting because it highlights the features that make C++ more powerful, and also
gives you a better understanding of the way the two languages work.
* Biggest one: C does not have classes and objects
* C++ has pass by reference. C does not.
* C++ implements name mangling when compiling functions, C does not.
===== C Preprocessor (CPP) =====
Much of what I have learned comes from two places: the GNU CPP manual
[[https://gcc.gnu.org/onlinedocs/gcc-8.3.0/cpp/|link]] and a guide to the CPP
[[https://docs.freebsd.org/info/cpp/cpp.pdf|link]].
''%%__VA_ARGS__%%'' is a CPP (c pre processor) identifier that gets replaced with the values
of ... when used in a variadic macro.
A simple macro is a kind of abbreviation. It is a name which stands for a fragment of
code. Some people refer to these as manifest constants.
Before you can use a macro, you must define it explicitly with the
''%%#define%%'' directive. ''%%#define%%'' is followed by the name of the macro
and then the code it should be an abbreviation for. For example,
#define BUFFER_SIZE 1020
The use of all upper case for macro names is a standard convention. Programs are easier
to read when it is possible to tell at a glance which names are macros.
The C preprocessor scans your program sequentially, so macro definitions take
effect at the place you write them.
foo = X;
#define X 4
bar = X;
Produces as output:
foo = X;
bar = 4;
You can also use ''%%#defines%%'' to define functions.
The ''%%do { } while(0)%%'' technique in macro definitions is used to avoid
issues with generating double expressions caused by the addition of a semicolon.
Doing the following:
#define SOME_MACRO(VAR) \
do { int i = var; \
i = 12*i; } \
while (0)
When you call this macro in the your code as ''%%SOME_MACRO(var);%%'' it expands into one
statement which is:
do { ... } while (0);
This way you can use a macro expansion in a if else statement with no curly braces
where more than one statement would mess stuff up.
===== C Declerations =====
First, understand the breakdown of a decleration in c.
===== Rule of Three =====
===== Rule of Five =====
===== STL containers =====
The STL library has 3 types of container classes:
* **sequence containers** - container classes that maintain the ordering of elements in the container. Examples are vectors, deques, and lists.
* **associative containers** - container classes that automatically sort their inputs when the inputs are inserted into the container. Eg. are a set, multiset, map or multimap.
* **container adapters** - special predefined containers that are adapted to specific uses, such as a LIFO stack or a FIFO queue.
STL containers provide a mechanism for traversing their contents called an iterator. An iterator is best visualized as a pointer to an element in the list with a set of overloaded operators that provide extra functionality.
Overloaded iterator operators:
* **Operator*** dereferencing an iterator gives the element that the item is pointing to
* **Operator++** advances the iterator to point to the next element
* **Operator== & !=** gives basic comparison for two iterators to see if they point to the same element.
* **Operator=** assign to a new location
Each container has functions that return an iterator.
* **begin()** returns an iterator at the beginning of the container
* **end()** returns an iterator at the start of the container
* **cbegin()** returns a ''%%const%%'' iterator at the start of the container
* **cend()** returns a ''%%const%%'' iterator at the end of the container
Iterators are members of an STL container. For example to get an iterator for a specific type of list:
std::map::const_iterator mapIt = myMap.cbegin();
==== Vector ====
An std::vector is a sequence container dynamic array that can grow to add to more elements.
==== Deque ====
An ''%%std::deque%%'' is double ended array that can grow from each end.
==== Pair ====
An ''%%std::pair%%'' is an object that holds a pair of objects.
// pair::pair example
#include // std::pair, std::make_pair
#include // std::string
#include // std::cout
int main () {
std::pair product1; // default constructor
std::pair product2 ("tomatoes",2.30); // value init
std::pair product3 (product2); // copy constructor
product1 = std::make_pair(std::string("lightbulbs"),0.99); // using make_pair (move)
product2.first = "shoes"; // the type of first is string
product2.second = 39.90; // the type of second is double
std::cout << "The price of " << product1.first << " is $" << product1.second << '\n';
std::cout << "The price of " << product2.first << " is $" << product2.second << '\n';
std::cout << "The price of " << product3.first << " is $" << product3.second << '\n';
return 0;
}
==== List ====
An ''%%std::list%%'' is a sequence container where each element contains a pointer to
the next and previous element. You can't randomly access elements, you have to
"walk the list". But inserting elements is very fast if you know where to insert
them.
==== Set ====
An ''%%std::set%%'' is an ordered list of unique elements that get automatically
sorted as we insert them.
==== Multiset ====
An ''%%std::multiset%%'' is an ordered list of elements that can contain
duplicate data which is automatically sorted as we insert them.
==== Map ====
An ''%%std::map%%'' is an associated array which is a map, symbol table or
dictionary that has a collection of key value pairs such that a key only shows
up once.
Data pairs must be inserted into a map, and while you do this they are
automatically sorted. You can make pairs with the ''%%std::make_pair(x,y)%%'' helper
function.
std::map myMap;
myMap.insert(std::make_pair(1, "mango"));
===== Memory Leaks =====
For every new there must be a delete. Use the following valgrind command to
profile for memory leaks [[https://www.cprogramming.com/debugging/valgrind.html|link]].
valgrind --tool=memcheck --leak-check=yes name_of_exec
===== Lambda Functions ======
Lambda functions are:
* functions without a name
* define their functionality right in place
* can be copied like data
Lambda functions should be precise and self explaining.
The syntax is as follows:
{{::screenshot_2019-03-13_17-07-19.png?400|}}
* [] : captures the used variables per copy of per reference
* () : is required for parameters
* -> : is required for a return value
* {} : may include expressions and statements
===== Range-based for statement =====
C++ 11 introduced the range-based ''%%for%%'' statement (([[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf|Section 6.5.4 c++ 11 standard]])) and takes the form:
for ( for-range-declaration : expression ) statement
Example:
int array[5] = { 1, 2, 3, 4, 5 };
for (int& x : array)
x *= 2;
===== Debugging =====
There are lots of options for debugging. I make extensive use of DDD with ROS
which helped a lot. gdbgui is an interesting web based front end, but i tried it
for 5 mins and ran into issues with it debugging a simple program.
==== GDB ====
Debugging in GDB is not that bad! It is also really useful when looking at simple
stuff for learning stuff.
This is a really nice intro [[http://www.thegeekstuff.com/2010/03/debug-c-program-using-gdb|link]].
This is a really nice video on gdbtui (which is the text user input) mode [[https://www.youtube.com/watch?v=RM3xwFxr9-Q|link]].
To debug in GDB you need to compile a program with a debug with a ''%%-g%%''
option.
For macros see the following [[https://sourceware.org/gdb/onlinedocs/gdb/Macros.html|link]].
===== Mutable =====
''%%mutable%%'' permits modification of the class member declared mutable even if the containing object is declared const.
int main()
{
int n1 = 0; // non-const object
const int n2 = 0; // const object
int const n3 = 0; // const object (same as n2)
volatile int n4 = 0; // volatile object
const struct
{
int n1;
mutable int n2;
} x = {0, 0}; // const object with mutable member
n1 = 1; // ok, modifiable object
// n2 = 2; // error: non-modifiable object
n4 = 3; // ok, treated as a side-effect
// x.n1 = 4; // error: member of a const object is const
x.n2 = 4; // ok, mutable member of a const object isn't const
const int& r1 = n1; // reference to const bound to non-const object
// r1 = 2; // error: attempt to modify through reference to const
const_cast(r1) = 2; // ok, modifies non-const object n1
const int& r2 = n2; // reference to const bound to const object
// r2 = 2; // error: attempt to modify through reference to const
// const_cast(r2) = 2; // undefined behavior: attempt to modify const object n2
}
Output:
# typical machine code produced on an x86_64 platform
# (only the code that contributes to observable side-effects is emitted)
main:
movl $0, -4(%rsp) # volatile int n4 = 0;
movl $3, -4(%rsp) # n4 = 3;
xorl %eax, %eax # return 0 (implicit)
ret
==== Pointer Syntax ====
sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;
Does not declare 3 pointers - it is one pointer and 2 objects.
sf::Sprite* unfortunately does not apply to all the variables declared following it, just the first. It is equivalent to
sf::Sprite* re_sprite_hair;
sf::Sprite re_sprite_body;
sf::Sprite re_sprite_eyes;
You want to do:
sf::Sprite *re_sprite_hair, *re_sprite_body, *re_sprite_eyes;
===== Smart Pointers =====
The STL library provides three types of "smart pointers", %%std::unique_ptr%%, %%std::shared_ptr%% and %%std::weak_ptr%%.