{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# In this chapter, we'll be learning the pointers and memory address"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstdio>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "int* mypointer;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(nil)"
     ]
    }
   ],
   "source": [
    "printf(\"%p\", mypointer);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## basics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5"
     ]
    }
   ],
   "source": [
    "int num = 5;\n",
    "printf(\"%d\", num);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "the memory address of 5 is 0x7fe40c1cc028"
     ]
    }
   ],
   "source": [
    "int *the_same_num = &num;\n",
    "printf(\"the memory address of %d is %p\", *the_same_num, the_same_num);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## arrow operator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It used to access the functions a pointer has."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstdio>\n",
    "\n",
    "struct Cat {\n",
    "    void dowhat() {\n",
    "        printf(\"Meow~\");\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "Cat a_cat;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "Cat* the_same_cat = &a_cat;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Meow~"
     ]
    }
   ],
   "source": [
    "the_same_cat -> dowhat();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## An array's pointer points to the first element of that array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int key_to_the_universe[] = {3, 6, 9};\n",
    "int* key_pointer = key_to_the_universe;\n",
    "*key_pointer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pass array to a function by using pointer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct College {\n",
    "    char name[256];\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "void print_names(College* colleges, size_t n) {\n",
    "    for (size_t i=0; i<n; i++) {\n",
    "        printf(\"%s\\n\", colleges[i].name);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "College fake_oxford[] = { {\"A\"}, {\"B\"}, {\"C\"} };"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A\n",
      "B\n",
      "C\n"
     ]
    }
   ],
   "source": [
    "print_names(fake_oxford, sizeof(fake_oxford)/sizeof(College));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  It can be very hard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*(fake_oxford[2]).name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*(&fake_oxford[2])->name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*(fake_oxford + 2)->name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*(*(fake_oxford + 2)).name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "College* another_college_pointer = &fake_oxford[2];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "@0x7ffddfc3d140"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "another_college_pointer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*another_college_pointer -> name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Instead of copying the outside variable to the inside of function everytime, we just use the same variable that come from the outside."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstdio>\n",
    "\n",
    "void a_function(int& the_same_variable_of_the_outside_scope) {\n",
    "    printf(\"%d\", the_same_variable_of_the_outside_scope);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8"
     ]
    }
   ],
   "source": [
    "int a_num = 8;\n",
    "a_function(a_num);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you change the reference variable value, the original value would also be changed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "void aaa(int& a_dd) {\n",
    "    a_dd = 10;\n",
    "}\n",
    "int b_num = 8;\n",
    "aaa(b_num);\n",
    "\n",
    "b_num"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Linked list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct Element {\n",
    "    Element* next{};\n",
    "    void insert_after(Element* new_element) {\n",
    "        //new_element->next = next;\n",
    "        next = new_element;\n",
    "    }\n",
    "    char prefix[2];\n",
    "    short operating_number;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "Element node1, node2, node3;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "node1.prefix[0] = 'T';\n",
    "node1.prefix[1] = 'K';\n",
    "node1.operating_number = 421;\n",
    "node1.insert_after(&node2);\n",
    "\n",
    "node2.prefix[0] = 'F';\n",
    "node2.prefix[1] = 'N';\n",
    "node2.operating_number = 222;\n",
    "node2.insert_after(&node3);\n",
    "\n",
    "node3.prefix[0] = 'L';\n",
    "node3.prefix[1] = 'S';\n",
    "node3.operating_number = 555;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "T,K,421\n",
      "F,N,222\n",
      "L,S,555\n"
     ]
    }
   ],
   "source": [
    "for (Element *cursor = &node1; cursor; cursor = cursor->next) {\n",
    "    printf(\"%c,%c,%d\\n\",\n",
    "         cursor->prefix[0],\n",
    "         cursor->prefix[1],\n",
    "         cursor->operating_number);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## More on References"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original: 100\n",
      "reference: 100\n"
     ]
    }
   ],
   "source": [
    "int original = 100;\n",
    "int& original_ref = original;\n",
    "printf(\"original: %d\\n\", original);\n",
    "printf(\"reference: %d\\n\", original_ref);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original: 200\n",
      "new value: 200\n",
      "reference: 200\n"
     ]
    }
   ],
   "source": [
    "int new_value = 200;\n",
    "original_ref = new_value;\n",
    "printf(\"original: %d\\n\", original);\n",
    "printf(\"new value: %d\\n\", new_value);\n",
    "printf(\"reference: %d\\n\", original_ref);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 'this' inside of a class (or struct)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "'this' representes the object itself inside the class.\n",
    "\n",
    "It is a pointer points to the object.\n",
    "\n",
    "It can be used to access the object's members or properties."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct AnObject {\n",
    "    private:\n",
    "        int how_old;\n",
    "    public:\n",
    "        void set_age(int how_old) {\n",
    "            this->how_old = how_old;\n",
    "            \n",
    "            how_old = how_old + 100;\n",
    "            printf(\"local variable or local function argument: %d\\n\", how_old);\n",
    "        }\n",
    "        void print_age() {\n",
    "            printf(\"class level variable or class property: %d\\n\", this->how_old);\n",
    "        }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "AnObject object;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "local variable or local function argument: 120\n",
      "class level variable or class property: 20\n"
     ]
    }
   ],
   "source": [
    "object.set_age(20);\n",
    "object.print_age();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 'const' methods"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A const method means that you won't change any object's property or variables inside of that function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct ConstMethodExample {\n",
    "    private:\n",
    "        int hi=2;\n",
    "    int a_function() const {\n",
    "        return this->hi;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Member initializer lists: another way for class property initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct Class {\n",
    "    int Num1, Num2;\n",
    "    Class(int a, int b) : Num1 {a} , Num2 {b} {\n",
    "        //I can do something else than manully set up Num1 and Num2\n",
    "    } \n",
    "    void print() const {\n",
    "        printf(\"%d, %d\", this->Num1, this->Num2);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "Class hi{ 1, 2 };"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1, 2"
     ]
    }
   ],
   "source": [
    "hi.print();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## auto type"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_60:3:1: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mindirection requires pointer operand ('std::initializer_list<int>' invalid)\u001b[0m\n",
      "*an_int\n",
      "\u001b[0;1;32m^~~~~~~\n",
      "\u001b[0m\u001b[1minput_line_60:2:7: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mredefinition of 'an_int'\u001b[0m\n",
      " auto an_int = { 4 };\n",
      "\u001b[0;1;32m      ^\n",
      "\u001b[0m\u001b[1minput_line_58:2:7: \u001b[0m\u001b[0;1;30mnote: \u001b[0mprevious definition is here\u001b[0m\n",
      " auto an_int = { 4 };\n",
      "\u001b[0;1;32m      ^\n",
      "\u001b[0m"
     ]
    },
    {
     "ename": "Interpreter Error",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Interpreter Error: "
     ]
    }
   ],
   "source": [
    "auto an_int { 4 };\n",
    "printf(\"%d\", an_int);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "auto a_int = 5;\n",
    "a_int"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"fuck\""
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "auto a_char_list { \"fuck\" };\n",
    "a_char_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"fuck\""
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "auto* whatever = &a_char_list;\n",
    "*whatever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"fuck\""
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "auto& no_way = a_char_list;\n",
    "no_way"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
