But hey we're all alive and everything eventually worked out. I got on the train and was 7 minutes late but they were like 7 minutes late picking me up after having barely found the train station on time after first having gone to the airport because ?????? So then they got lost trying to get back to the place they had already been to (the airport) because THAT FUCKING GUY WITH THE PINK HAIR (chris) wanted to use his STUPID PHONE instead of USING A GODDAMN MAP LIKE YOU SHOULD. We finally got to the airport and then Sam missed the turn so we almost LEFT the airport until I was like OK JUST FUCKING TURN RIGHT HERE OK? So then we turned around, managed to get into the airport parking, took a tram to the terminal, walked into the nearest door for baggage claim and exactly 3 seconds after walking inside there was a big fat announcement: "WILL SAMUEL BOYD, CHRIS icantremember, AND ERIK MCCLURE PLEASE PICK UP THEIR PASSENGER AT BAGGAGE CLAIM 8?" and we all RAN DOWN TO BAGGAGE CLAIM 8 to rescue zone WHO HADN'T SLEPT IN LIKE 40 HOURS. So then we got out of Portland, which I am now convinced was designed specifically to kill people, and it took like and hour and a half to get back home and we JUST BARELY got to the apartment before midnight and then we played games for two hours and passed out. And then we woke up like every 3 hours and SAM'S FUCKING SNORING KEPT WAKING ME UP OH MY GOD but eventually we sort of all got to sleep. Also the bathroom door squeaks.
BUT WE AREN'T DEAD :D
July 16, 2011
July 6, 2011
Radians: An explanation
Radians are used in almost everything that involves computers, and often come up in mathematical equations. However, most people are used to measuring angles in degrees, even though degrees (unlike radians) are a completely arbitrary measurement. To understand Radians, you need to understand $$\pi$$, or more precisely, why it sucks. Like a black hole, except black holes don't actually suck, they just warp space-time so you fall into them OK BACK ON TOPIC:
$$\pi$$ is the ratio of a circle's diameter to its circumference. This is retarded. When was the last time you thought of a circle using its diameter for crying out loud? We define circles, and should intuitively think of circles using their radius, which is the distance from the center to any point on the edge of the circle.

source: wikimedia commons
So that means that the ratio of the radius to the circumference is actually $$2\cdot\pi$$. This is why the formula for the circumference of a circle is $$2\cdot\pi\cdot r$$. In fact, its why we end up using $$2\cdot\pi$$ almost everywhere, because we almost always define circles with the radius, but $$\pi$$ is in relation to the diameter. Which is just stupid, and is in fact so stupid that some people are currently trying to define $$\tau$$ (Tau) such that $$\tau = 2\cdot\pi$$. Sadly, $$2\pi$$ still rules the world. I guess mathematicians really like pie...?
Either way, we must work within our constaints. So, keeping in mind that $$2\pi$$ is the ratio between a circle's circumference and its radius, what happens if you have a unit circle (a circle with a radius of 1)? Well, that means it has a diameter of 2, so if you roll it out on the number line, you get this:

source: wikimedia commons
When we talk about rotation and angles in radians, we are using the following relation:
\[ 360^{\circ} = 2\pi\;rad \]That is, in radians, or $$rad$$ as it is commonly abbreviated, a full rotation is $$2\pi$$ because that's the circumference of a circle with a radius of 1. Radius → Radians. We know why its $$2\pi$$ instead of just $$pi$$, because $$pi$$ is stupid. If you want, you can say that $$\tau = 2\pi$$, so that $$\tau$$ is then equal to the ratio between a circle's radius and its circumference. Then we get the much nicer relation:
\[ 360^{\circ} = \tau\;rad \]360° is just one rotation of a circle. A radian is simply how far around the circumference of a unit circle you want to go. So that means 180° is halfway around the circle, which is $$\tau/2$$ or just $$\pi$$ radians.
This gives rise to the conversion functions:
\[ \begin{aligned}
rad = deg \cdot \left(\frac{\pi}{180}\right) \\
deg = rad \cdot \left(\frac{180}{\pi}\right)
\end{aligned}
\] But these simply arise out of $$2\pi$$ being simplified:
\[ \begin{aligned}
rad = deg \cdot \left(\frac{2\pi}{360}\right) \\
deg = rad \cdot \left(\frac{360}{2\pi}\right)
\end{aligned}
\] So now we have an intuitive explanation of what radians are - the distance around the circumference of the unit circle.
$$\pi$$ is the ratio of a circle's diameter to its circumference. This is retarded. When was the last time you thought of a circle using its diameter for crying out loud? We define circles, and should intuitively think of circles using their radius, which is the distance from the center to any point on the edge of the circle.
source: wikimedia commons
So that means that the ratio of the radius to the circumference is actually $$2\cdot\pi$$. This is why the formula for the circumference of a circle is $$2\cdot\pi\cdot r$$. In fact, its why we end up using $$2\cdot\pi$$ almost everywhere, because we almost always define circles with the radius, but $$\pi$$ is in relation to the diameter. Which is just stupid, and is in fact so stupid that some people are currently trying to define $$\tau$$ (Tau) such that $$\tau = 2\cdot\pi$$. Sadly, $$2\pi$$ still rules the world. I guess mathematicians really like pie...?
Either way, we must work within our constaints. So, keeping in mind that $$2\pi$$ is the ratio between a circle's circumference and its radius, what happens if you have a unit circle (a circle with a radius of 1)? Well, that means it has a diameter of 2, so if you roll it out on the number line, you get this:
source: wikimedia commons
When we talk about rotation and angles in radians, we are using the following relation:
\[ 360^{\circ} = 2\pi\;rad \]That is, in radians, or $$rad$$ as it is commonly abbreviated, a full rotation is $$2\pi$$ because that's the circumference of a circle with a radius of 1. Radius → Radians. We know why its $$2\pi$$ instead of just $$pi$$, because $$pi$$ is stupid. If you want, you can say that $$\tau = 2\pi$$, so that $$\tau$$ is then equal to the ratio between a circle's radius and its circumference. Then we get the much nicer relation:
\[ 360^{\circ} = \tau\;rad \]360° is just one rotation of a circle. A radian is simply how far around the circumference of a unit circle you want to go. So that means 180° is halfway around the circle, which is $$\tau/2$$ or just $$\pi$$ radians.
| Degrees | Radians |
|---|---|
| 360° | $$2\pi$$ |
| 180° | $$\pi$$ |
| 90° | $$\frac{\pi}{2}$$ |
| 60° | $$\frac{\pi}{3}$$ |
| 45° | $$\frac{\pi}{4}$$ |
| 30° | $$\frac{\pi}{6}$$ |
This gives rise to the conversion functions:
\[ \begin{aligned}
rad = deg \cdot \left(\frac{\pi}{180}\right) \\
deg = rad \cdot \left(\frac{180}{\pi}\right)
\end{aligned}
\] But these simply arise out of $$2\pi$$ being simplified:
\[ \begin{aligned}
rad = deg \cdot \left(\frac{2\pi}{360}\right) \\
deg = rad \cdot \left(\frac{360}{2\pi}\right)
\end{aligned}
\] So now we have an intuitive explanation of what radians are - the distance around the circumference of the unit circle.
C# to C++ Tutorial - Part 1: Basics of Syntax
[ 1 · 2 · 3 · 4 · 5 · 6 · 7 ]
When moving from C# to C++, one must have a very deep knowledge of what C# is actually doing when you run your program. Doing so allows you to recognize the close parallels between both languages, and why and how they are different. This tutorial will assume you have a fairly strong grasp of C#, but may not be familiar with some of its more arcane attributes.
In C#, everything is an object, or a static member of an object. You can't have a function just floating around willy-nilly. However, like all programs, a C# program must have an entry-point. If you have primarily done GUI-based design, you probably aren't aware of the entry-point that is automatically generated, but it is definitely there, and like everything else, it's part of an object. C# actually allows you to change the entry point function, but a default C# project will automatically generate a Program.cs file that looks like this:
Now, counting the number of bytes you are pumping into the stream is really annoying, and that's what the insertion operator does for you; it properly formats everything automatically. That's all. It's not a demon from hell bent on destroying your life, its just weird syntax. I don't know why they don't also have this functionality in a much easier to understand overloaded function, but there are a lot of things that they don't do, so we'll just have to live with it.
The
So now that we have a direct analogue between C# and C++ in terms of where our application starts, we need to deal with a conceptual difference in how C# and C++ handle dependencies. In C#, your class file is just
C++, on the other hand, does not do behind-the-scenes magic to help you resolve your dependencies. To understand what C++ is doing, one must understand how any compiler resolves references inside code (including C#). When the C# compiler is compiling your project, it goes through each of your code files one by one and compiles everything to an intermediate object code that will later be compiled down into the machine code (or, in this case, bytecode, since C# is an interpreted language). But wait, what if it's compilingTHIS IS IMPOSSIBLE OH GOD WE'RE GOING TO DIE No, it's actually quite simple to deal with. Enter prototypes. If you have the following C# class:
Making "prototypes" of these functions (which C# doesn't have so this will be invalid syntax) would be the following:
Notice the distinct lack of code - this is how circular references get resolved. It turns out that to properly compile your program, the compiler only has to know what a function takes in as arguments, and what it returns. By treating the function as a "black box" of sorts, the compiler can ignore whatever code is inside it. Notice that this applies to constructors and destructors as well - they are simply special functions inside the class. In this manner the entire class can be treated as a bunch of black-box functions that don't actually have any code that needs to be compiled in them. What the C# compiler does is create a bunch of these prototypes behind the scenes and feed them in front of all your code files, so it first compiles
But wait, what if
Thankfully, we don't have to worry about this, since thinking of class functions as functions that operate on the object is a lot more intuitive. However, one must be aware that even in inheritance scenarios, everything is just a function, or an overload of a virtual function, or something similar (if you do not know what virtual functions are, you need to learn more C# before proceeding). Consequently, our ability to declare function prototypes solves all the dependency issues, because everything is a function.
This is where we get into exactly what the
Header files contain class and function prototypes, and code files contain all the actual code. A C++ project is therefore defined entirely by a list of .cpp files that need to be compiled. Header files are just little helper files that make resolving dependencies easier. C# does this for you - C++ does not. Note that because these are technically arbitrary file distinctions, you can put whatever you want in either file type; nothing will stop you from doing
So what we're doing when we say
Consequently, unless you know what your doing, you should keep code out of header files. C++ doesn't prevent you from throwing functions that aren't attached to classes all over the place, like C# does, so what would happen if you defined
At this point I want to clarify what
Now we just have one more hurdle to overcome with the "Hello World" application, that funky
Everything in your entire program takes up memory. Since this tutorial is designed for people who know C# already, I really, really hope you already knew that. What you might not know is that all this memory has a specific location on the machine. In fact, on a 32-bit machine, every single possible location of a byte can be contained in an unsigned 32-bit integer. This is why we are currently moving to 64-bit CPUs, because an unsigned 32-bit integer can only hold up to 4294967295 possible byte locations, which amounts to 4.2 gigs of memory. That's why you are limited to 4 gigs of RAM on a 32-bit machine, and windows has difficulty using more than 2 gigs because a lot of older programs assumed that a signed 32-bit integer was sufficient for all memory addresses, so windows has to do some funky memory paging techniques to get programs that ignore the last bit to use memory locations above 2147483647.
So, if you allocate a float, either on the stack or on the heap, it must exist somewhere within those 4294967295 possible byte locations. Consequently, lets say you want to call a function that modifies that float, but the function has to have a void return value for some arbitrary reason. If you know where in memory that float is, you can tell the function where to find the float and modify it to the desired value without ever returning a value. Here is an example C++ function doing just that (which is syntactically valid all by itself because C++ allows functions outside of classes):
What's going on here? First, we have our
The next thing done in
This is the exact same as the previous function, but here we can clearly see the reference. In C#, if you wanted a variable normally passed by value, like a struct, to get passed by reference, you had to override the default behavior by adding
This does the same thing, just without the pointer. In fact, we can totally ignore the pointer in C++ too, if we want (which I tend to prefer, when possible, because its a lot easier to work with):
Now, in this implementation, you will notice that our call to
As we can see, pointers are just the underlying work behind references. If you ever go into Managed C++, you'll find out that all C# references are really just pointers, but the language treats them as references so they're hidden from you. In C++, you can have both pointers and references. It is important to note that you can only initialize a reference variable. Any subsequent operators will be applied to whatever variable its referencing, making it impossible to get the address of a reference variable or do anything to the reference variable itself - for all intents and purposes, it just is the variable it references. This is why pointers are handy - you CAN reassign the actual pointer variable while also accessing the variable its pointing to. Consequently, you can also get the address of a pointer variable, since just like any other variable, including the reference variable, it must occupy memory, and therefore has a location that you can get a pointer to (we'll get to that syntax in a minute). But there's one more thing...
What about arrays? In C#, arrays are actually a built-in class that has lots of fancy functions and whatnot. Interestingly, they are still of fixed size. C++ arrays are also fixed size, but they are manipulated as raw memory. Let's compare initializing an array in C++ and initializing an array in C#:
It should be pretty obvious at this point that arrays are pointers in C++. I can even rewrite the above in C++ using an empty array syntax, and it will be equally as valid:
Same thing. In fact, if you watch your compiler output carefully, you might even see the compiler internally convert all the arrays to pointers when its resolving types. Now, as a C# programmer, you should already know what arrays are. You should probably also be at least dimly aware that each element of an array occupies memory directly after the element proceeding it. So, if you know where the address of the first element is, you know the second element is exactly x bytes afterwards, where x is the number of bytes your type takes up. This is why pointers have types associated with them - we know that
So pointers can be treated as arrays that behave exactly the same way a C# array does. However, the astute C# programmer would ask, how do you know how long the array is?
Enter every single buffer overflow error that has been the bane of man since the beginning of time. YOU have to keep track of how long the array is, and you'd better be damn sure you don't get it wrong. Consequently any function taking an array of variable size will also require a separate argument telling the function how many elements are in the array. Usually arrays are just constructed on the stack with a constant, known size, which is often harmless and pretty hard to screw up. If you start doing funky things with them, though, you might want to look up std::vector for an encapsulated dynamic array.
So C++ arrays are just like C# arrays, except they are pointers to the first element, and you don't know how long they are (and they might cause the destruction of the universe if you screw up). You should already know that a string is an array, and consequently in C++ the standard string type is
There's a lot of stuff about pointers that this tutorial hasn't covered, like function pointers and pointer arithmetic, which we'll get to next time.
Part 2: Pointers To Everything
When moving from C# to C++, one must have a very deep knowledge of what C# is actually doing when you run your program. Doing so allows you to recognize the close parallels between both languages, and why and how they are different. This tutorial will assume you have a fairly strong grasp of C#, but may not be familiar with some of its more arcane attributes.
In C#, everything is an object, or a static member of an object. You can't have a function just floating around willy-nilly. However, like all programs, a C# program must have an entry-point. If you have primarily done GUI-based design, you probably aren't aware of the entry-point that is automatically generated, but it is definitely there, and like everything else, it's part of an object. C# actually allows you to change the entry point function, but a default C# project will automatically generate a Program.cs file that looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ScheduleTimer
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true);
Application.Run(new frmMain());
}
}
}
static void Main() is the real entry point for your application, which simply initializes visual styles and then immediately launches the form that most C# users are accustomed to working with. Now, we can compare this with a simple "Hello World" C++ program:#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "Hello World";
return 0;
}
This program, to a C# user, immediately looks foreign and possibly even outright hostile. However, almost everything in it has a direct analogue in C#, despite the rather inane syntax that is being used. The most glaring example here is the insertion operator, <<, because almost no one ever uses it except for in streams and the fact that it's in a C++ Hello World program creates an absurd amount of confusion. It's just a fancy way of doing this:
#include <iostream>
int main(int argc, char *argv[])
{
std::cout.write("Hello World",11);
return 0;
}
Now, counting the number of bytes you are pumping into the stream is really annoying, and that's what the insertion operator does for you; it properly formats everything automatically. That's all. It's not a demon from hell bent on destroying your life, its just weird syntax. I don't know why they don't also have this functionality in a much easier to understand overloaded function, but there are a lot of things that they don't do, so we'll just have to live with it.
The
main() function here serves the same exact purpose as the Main() function in C#. Strict C++ requires you to have a main() function to serve as an entry point, but various operating systems modify it and, in the case of Windows, outright replace it. As such, you will notice that your "hello world" C++ program, when built, opens in a command line. You will learn later how to prevent this by using Windows' proprietary entry function. For those of you familiar with C#, this is exactly the same as C#'s ability to change around the entry point of the application, and you can even make a command line application in C# too by properly changing the compiler settings. The same concept applies to C++, but unlike C#, which defaults to a GUI, C++ defaults to a command line. Changing the compiler settings properly will result in a C++ program that starts in a GUI, just like C# (although unlike C#, C++ doesn't have any help, which turns GUI programming into a complete nightmare).So now that we have a direct analogue between C# and C++ in terms of where our application starts, we need to deal with a conceptual difference in how C# and C++ handle dependencies. In C#, your class file is just
Class.cs, your helper class is Helper.cs, and both of them can call the other one provided they are in the same namespace, or if you are inheriting someone else's, using the correct using statements to resolve the code. If these concepts are not familiar to you, you should learn more about C# before delving further into C++.C++, on the other hand, does not do behind-the-scenes magic to help you resolve your dependencies. To understand what C++ is doing, one must understand how any compiler resolves references inside code (including C#). When the C# compiler is compiling your project, it goes through each of your code files one by one and compiles everything to an intermediate object code that will later be compiled down into the machine code (or, in this case, bytecode, since C# is an interpreted language). But wait, what if it's compiling
Class.cs before Helper.cs even though Class instantiates a Helper object and calls some functions inside of it that then instantiate another Class object? Well, what if you compiled Helper.cs first... but Helper.cs needs Class.cs to be compiled first because its instantiating a Class object inside the function that the Class object is calling! That's a circular dependency! using System;
namespace FunFunBunBuns
{
class Class
{
private int _yay;
private int _bunnies;
// Constructor
public Class(int yay)
{
_yay = yay;
_bunnies = 0; // :C
}
// Destructor
public ~Class()
{
_yay = 0;
}
public void IncrementYay()
{
_yay++;
}
public int MakeBunnies(int num) // :D
{
_bunnies = _bunnies + num;
return _bunnies;
}
}
}
Making "prototypes" of these functions (which C# doesn't have so this will be invalid syntax) would be the following:
using System;
namespace FunFunBunBuns
{
class Class
{
private int _yay;
private int _bunnies;
// Constructor
public Class(int yay);
// Destructor
public ~Class();
public void IncrementYay();
public int MakeBunnies(int num);
}
}
Notice the distinct lack of code - this is how circular references get resolved. It turns out that to properly compile your program, the compiler only has to know what a function takes in as arguments, and what it returns. By treating the function as a "black box" of sorts, the compiler can ignore whatever code is inside it. Notice that this applies to constructors and destructors as well - they are simply special functions inside the class. In this manner the entire class can be treated as a bunch of black-box functions that don't actually have any code that needs to be compiled in them. What the C# compiler does is create a bunch of these prototypes behind the scenes and feed them in front of all your code files, so it first compiles
Class.cs using a prototype of the Helper class, which allows it to instantiate and use any functions that Helper defines without actually knowing the code inside them. Then, it compiles Helper.cs, compiling assigning code to the previously empty black-box functions defined in the Helper prototype, using a prototype of Class so that it can also instantiate and call functions from Class. In this way, both Helper.cs and Class.cs can be compiled in any order.But wait, what if
Class inherits Helper? In reality, this changes nothing. An important lesson here is that, in C++, you will not be able to simply ignore the fact that everything is a function. Classes are just an abstraction - in reality, inheritance, constructors, deconstructors, operators, everything is just various special functions. Python's class syntax is interesting because requires that all class functions explicitly define the self parameter (which is identical to the this reference in C++ and C#), even the class constructor. Both C++ and C# hide all this from you, so Constructors and Destructors and class functions all magically just work, even though underneath it all they're just ordinary functions with a special parameter that's hidden from view. This is, in fact, how one mimics class behavior in C, which does not have object-oriented features - simply build a struct and make a bunch of functions for it that take a "this" pointer, or a pointer to a specific struct on which the function operates. This behavior can be (needlessly) duplicated using C# - let's transform our Class class to C-style function implementations, ignoring the slightly invalid C# syntax.using System;
namespace FunFunBunBuns
{
struct Class
{
private int _yay;
private int _bunnies;
};
public Constructor(Class this, int yay)
{
this._yay = yay;
this._bunnies = 0; // :C
}
public Destructor(Class this)
{
this._yay = 0;
}
public void IncrementYay(Class this)
{
this._yay++;
}
public int MakeBunnies(Class this, int num) // :D
{
this._bunnies = this._bunnies + num;
return this._bunnies;
}
}
Thankfully, we don't have to worry about this, since thinking of class functions as functions that operate on the object is a lot more intuitive. However, one must be aware that even in inheritance scenarios, everything is just a function, or an overload of a virtual function, or something similar (if you do not know what virtual functions are, you need to learn more C# before proceeding). Consequently, our ability to declare function prototypes solves all the dependency issues, because everything is a function.
This is where we get into exactly what the
#include directive is for. In C#, all your files are automatically accessible from every other file, and this isn't a problem because compilation is nigh-instantaneous. C++ is much more intensive to compile, partially because it doesn't have a precompiled 400 MB library of crap to work off of, and partially due to a much more complicated precompiler. That means in C++, if you want a given file to have access to another file, you have to #include that file. In our Hello World application, we are including iostream, which does not have a .h file extension on the end for stupid regulatory reasons. However, what about the file our code is in? Our code is not in a .h file, its in a .cpp file. This is where we get to a critical difference between C# and C++. While C# just has .cs files for code, C++ has two types of files: header files and code files..cpp == C++ (C-plus-plus) code file
.h = C++ Header fileHeader files contain class and function prototypes, and code files contain all the actual code. A C++ project is therefore defined entirely by a list of .cpp files that need to be compiled. Header files are just little helper files that make resolving dependencies easier. C# does this for you - C++ does not. Note that because these are technically arbitrary file distinctions, you can put whatever you want in either file type; nothing will stop you from doing
#include "main.cpp", its just ridiculous and confusing. Both #include <> and #include "" are valid syntax for the #include directive, there is no real difference. Standard procedure, however, is that #include <> is used for any header files outside of your project, and #include "" is used for header files inside your project, or closely related to it.So what we're doing when we say
#include <iostream> is that we're including a bunch of prototypes for various input/output stream (i/o stream --> iostream) related classes defined in the standard library, which your compiler already has the corresponding .cpp implementations of built into it. So, the compiler links the application against this header file, and when you use std::cout, it just treats everything in it (including that ridiculously obtuse << operator, which is really just another function) as a black-box function.Consequently, unless you know what your doing, you should keep code out of header files. C++ doesn't prevent you from throwing functions that aren't attached to classes all over the place, like C# does, so what would happen if you defined
int ponies() { return 0; } in a header file that you include in two seperate .cpp files? The compiler will try to compile the function twice, and on the second time it will explode because the function it tried to put code into already had code in it, since it wasn't a prototype! EVERYTHING DIES! So until you get to the more advanced areas of C++, don't put code in your header files (unless you want to watch your compiler die, you monster).At this point I want to clarify what
std:: is, because it looks rather weird to a C# programmer. In C#, the . operator works on everything - you just have System.Forms.Whatever.Help.Im.Trapped.In.A.Universe.Factory.Your.Class.Member.Function() and its all good. In C++, that's not going to work anymore. The :: operator is known as the Scope Resolution Operator. It's a lot easier to explain if I first explain what the . operator has been demoted to. You can only use the . operator on a reference or value type of an instantiated object (basically everything you've ever worked with in C#). The important distinction here is that static functions cannot be accessed with the . operator anymore. This is because Static functions, along with namespaces and typedefs and everything else must use the Scope Resolution Operator. Consequently, you can think of the . operator as being demoted to just calling class functions, and everything else now uses the :: operator. So, std::cout just means that we're access the cout class in the std namespace.Now we just have one more hurdle to overcome with the "Hello World" application, that funky
char* argv[] parameter in main(). Most C# programmers can correctly infer that it is probably an array of some sort, but we don't know what type char* is, other than its clearly related to char.char* is a pointer. Yes, the same scary pointers you hear about all the time. No, they aren't really scary. In fact, you have been using similar concepts in C# all the time without actually realizing it. First, however, let's take a hard look at what a pointer really is.Everything in your entire program takes up memory. Since this tutorial is designed for people who know C# already, I really, really hope you already knew that. What you might not know is that all this memory has a specific location on the machine. In fact, on a 32-bit machine, every single possible location of a byte can be contained in an unsigned 32-bit integer. This is why we are currently moving to 64-bit CPUs, because an unsigned 32-bit integer can only hold up to 4294967295 possible byte locations, which amounts to 4.2 gigs of memory. That's why you are limited to 4 gigs of RAM on a 32-bit machine, and windows has difficulty using more than 2 gigs because a lot of older programs assumed that a signed 32-bit integer was sufficient for all memory addresses, so windows has to do some funky memory paging techniques to get programs that ignore the last bit to use memory locations above 2147483647.
So, if you allocate a float, either on the stack or on the heap, it must exist somewhere within those 4294967295 possible byte locations. Consequently, lets say you want to call a function that modifies that float, but the function has to have a void return value for some arbitrary reason. If you know where in memory that float is, you can tell the function where to find the float and modify it to the desired value without ever returning a value. Here is an example C++ function doing just that (which is syntactically valid all by itself because C++ allows functions outside of classes):
void ModifyFloat(float* p)
{
*p = 100.0;
}
int main(int argc, char* argv[])
{
float x = 0; //x is equal to 0.0
ModifyFloat( &x );
// x is now equal to 100.0
}
What's going on here? First, we have our
ModifyFloat() function. This takes a pointer to a float, which is declared by adding a * to the desired type we want to make a pointer to. Remember that pointers are really just 32-bit integers (or 64-bit if you have a 64-bit operating system), but C++ assigns them a type so that if you try to assign a double to a pointer to a float, it throws an error instead of overflowing 4 extra bytes, causing a heap corruption and destroying the universe. So char* is a pointer to a char, a double* points to a double, and Helper* is a pointer to our own Helper class.The next thing done in
ModifyFloat() is *p. In this case, the * operator is the dereference operator. So unfortunately * is the multiply, pointer, and dereference operator in C++. Yes, this is retarded. I'm sorry. But what the heck does dereference even mean? It takes a pointer type and turns it into a reference. You already know what a reference is, even if you don't realize it. In C#, you can pass a variable of your Helper class into a function, modify the class in the function, and the original variable will get modified too! This is because, by default, classes are passed by-reference in C#. That means, even though it looks identical to a variable passed by value, any changes made to the variable are in fact made to whatever variable it references. So, this idea of passing variables in by reference should be familiar to an experienced C# programmer. C++ has references too, I just haven't gone over their syntax. Here's a more explicit version of the function:void ModifyFloat(float* p)
{
float& ref_p = *p;
ref_p = 100.0;
}
This is the exact same as the previous function, but here we can clearly see the reference. In C#, if you wanted a variable normally passed by value, like a struct, to get passed by reference, you had to override the default behavior by adding
ref. In C++, a variable that is a reference to a given type is declared in a similar manner to a pointer. The & operator is used instead of *, so in this example, float& is a reference to a float. We assign it to the value produced by turning our pointer into a float reference. Then we just set our reference equal to 100.0 and it magically alters the original variable, just like it would in C#. In fact, here is the same function written in (slightly illegal) C#:public static void ModifyFloat(ref float p)
{
p=100.0;
}
This does the same thing, just without the pointer. In fact, we can totally ignore the pointer in C++ too, if we want (which I tend to prefer, when possible, because its a lot easier to work with):
void ModifyFloat(float& ref_p)
{
ref_p = 100.0;
}
int main(int argc, char* argv[])
{
float x = 0; //x is equal to 0.0
ModifyFloat( x );
// x is now equal to 100.0
}
Now, in this implementation, you will notice that our call to
ModifyFloat is now equivalent to what it would be in C#, in that we just pass in the variable. What happened to that random & operator we had there before? The & operator is also known as the address-of operator, meaning when its applied to a variable as opposed to a type, it returns a pointer to that variable (yay, more context-dependent redundant operators). So, we could rewrite our function as follows to make it a bit more clear:void ModifyFloat(float* p)
{
float& ref_p = *p; //get a reference from the pointer
ref_p = 100.0; //modify the reference
}
int main(int argc, char* argv[])
{
float x = 0; //x is equal to 0.0
float* p_x = &x; //get a pointer to x
ModifyFloat( p_x ); //pass pointer into function
// x is now equal to 100.0
}
As we can see, pointers are just the underlying work behind references. If you ever go into Managed C++, you'll find out that all C# references are really just pointers, but the language treats them as references so they're hidden from you. In C++, you can have both pointers and references. It is important to note that you can only initialize a reference variable. Any subsequent operators will be applied to whatever variable its referencing, making it impossible to get the address of a reference variable or do anything to the reference variable itself - for all intents and purposes, it just is the variable it references. This is why pointers are handy - you CAN reassign the actual pointer variable while also accessing the variable its pointing to. Consequently, you can also get the address of a pointer variable, since just like any other variable, including the reference variable, it must occupy memory, and therefore has a location that you can get a pointer to (we'll get to that syntax in a minute). But there's one more thing...
What about arrays? In C#, arrays are actually a built-in class that has lots of fancy functions and whatnot. Interestingly, they are still of fixed size. C++ arrays are also fixed size, but they are manipulated as raw memory. Let's compare initializing an array in C++ and initializing an array in C#:
int[] numbers = new int[5];
int* numbers = new int[5];
It should be pretty obvious at this point that arrays are pointers in C++. I can even rewrite the above in C++ using an empty array syntax, and it will be equally as valid:
int numbers[] = new int[5];
int x[] is identical to int* x. There is no difference. Observe the following modification of our original Hello World function:int main(int argc, char** argv);
Same thing. In fact, if you watch your compiler output carefully, you might even see the compiler internally convert all the arrays to pointers when its resolving types. Now, as a C# programmer, you should already know what arrays are. You should probably also be at least dimly aware that each element of an array occupies memory directly after the element proceeding it. So, if you know where the address of the first element is, you know the second element is exactly x bytes afterwards, where x is the number of bytes your type takes up. This is why pointers have types associated with them - we know that
float* points to an array of elements, and that each element takes up 4 bytes. To verify this, the sizeof() built-in function/operator/whatever will return the number of bytes a given type, class, or struct takes up. That's the number of bytes we skip ahead to get to the next element in an array. This is all done transparently in C++ using the same array index operator as C# uses:int main(int argc, char** argv)
{
int* ponies = new int[5];
ponies[0] = 1; //First element..
ponies[1] = 2; //Second element...
}
So pointers can be treated as arrays that behave exactly the same way a C# array does. However, the astute C# programmer would ask, how do you know how long the array is?
YOU DON'T
Enter every single buffer overflow error that has been the bane of man since the beginning of time. YOU have to keep track of how long the array is, and you'd better be damn sure you don't get it wrong. Consequently any function taking an array of variable size will also require a separate argument telling the function how many elements are in the array. Usually arrays are just constructed on the stack with a constant, known size, which is often harmless and pretty hard to screw up. If you start doing funky things with them, though, you might want to look up std::vector for an encapsulated dynamic array.
So C++ arrays are just like C# arrays, except they are pointers to the first element, and you don't know how long they are (and they might cause the destruction of the universe if you screw up). You should already know that a string is an array, and consequently in C++ the standard string type is
const char*, not string. You also can't put them in switch() statements. Sorry.There's a lot of stuff about pointers that this tutorial hasn't covered, like function pointers and pointer arithmetic, which we'll get to next time.
Part 2: Pointers To Everything
June 19, 2011
On Hacking (or Why We Need Security Ratings)
Another website has been hacked. It seems almost routine now, with site after site getting demolished by hackers. The overwhelming public response to the catastrophe has been to ask, "can anything be made secure?" Security experts, naturally, are constantly attacking the companies in question for their dismal security practices, but what of the general public? They don't know what a hash is. They don't know what an SQL injection is. They have no reason to know these things and will never understand them. All they understand is that their company assured them they had good security, and then they were hacked, and somehow the good security wasn't actually good. So then they'll move to another company, and this time, they're told, this company really does have good security. But nope, it got hacked too, guess that good security wasn't actually good.
Can any security be good? A security expert knows why the companies were hacked and can answer that question - the average Joe probably won't be able to. This is the crux of the problem - What is good security? How can an average person figure out what good security is? Good security used to be MD5 hashing. Then it was MD5 hashing with a seed. Now MD5 is cryptographically insecure, so we're trying to move to SHA1, but even that might be crackable in the near future, so someone invented bcrypt, but now the bcrypt implementation has demonstrated some unnerving behavior, making its implementation unverified. Then there is SQL injection vulnerabilities and the long list of XSS attacks, along with cookiejacking made possible by unencrypted networks and Firesheep. Even now we are seeing weaknesses at the highest echelons of security - hacked RSA databases and even HTTPS certificates.
Answering our question of what good security is clearly isn't easy. Of course, what if we assume that all security is broken? We would have to outlaw all hacking and seriously punish the offenders because there is nothing that can be done to lock up the system. This approach, however, is inherently flawed. For one, it is closely related to the drug war waged by the U.S. authorities, which has been astoundingly ineffective at stopping the drug trade. Not because it can't shut down drug-rings (it's very good at doing that), but simply because the business is so profitable that for every player you kill in the game, another one crops up to take their place. Lulzsec serves as a harbinger of that scenario, where hacking is cheap, and even if you throw everyone involved in jail, someone else will replace them.
However, even this scenario is being optimistic. If security is near impossible, computers become useless. The real world would turn into Hollywood, where electronics are easily bypassed. The problem is that if computer security is easily bypassed, people will stop using it. Online transactions die. The paper trail comes back. People refuse to put their personal details in anything that could be digitized. Everything that has enabled the technological explosion of today would get stuck in a tug-of-war between security and convenience. If history is anything to go by, the public would rather give up the last bits of their privacy just so they could use all the conveniences of electronics without having to worry about hackers. Suddenly we live in 1964.
This scenario may seem implausible to you because it is. Computer security can be effective, it simply needs to be done properly, which is not impossible. It may be difficult, but so is starting a successful company, and that doesn't seem to stop any of the entrepreneurs. The problem we face is that the average customer has no way of discerning good security from bad security. If they could, market pressures would force companies to adapt the best security possible, or customers would take their data elsewhere. Security is crap because no one knows what security is other then the security experts.
We have building inspectors and elevator certifications and health inspectors... why not security inspectors? It doesn't need to be government mandated, considering the government's track record, it might be a lot better if a private company or group provided the service, but somehow, there needs to be a way to measure security in a verifiable manner. There are two ways I know of to do this (there may be others) - from the inside, and from the outside. An inside inspection is more reliable when done properly, but more likely to be corrupted and gamed. An outside inspection, however, doesn't rely on the consent of a company to plaster a security rating on them. The downside is that an outside inspection requires pummeling the company's product blindly, which will only catch the really stupid mistakes, and not the dangerous middle-ground between really bad security and really good security.
I'm not pretending I know how to solve this problem. I don't, but I do know that someone needs to figure this out. If we are going to make any headway with security, the general public needs a friendly, easy, intuitive way to check the security rating of a company, instead of relying on the company's insistence that it uses a "very sophisticated security system". Only then will market pressures push for the resurgence of proper security.
Can any security be good? A security expert knows why the companies were hacked and can answer that question - the average Joe probably won't be able to. This is the crux of the problem - What is good security? How can an average person figure out what good security is? Good security used to be MD5 hashing. Then it was MD5 hashing with a seed. Now MD5 is cryptographically insecure, so we're trying to move to SHA1, but even that might be crackable in the near future, so someone invented bcrypt, but now the bcrypt implementation has demonstrated some unnerving behavior, making its implementation unverified. Then there is SQL injection vulnerabilities and the long list of XSS attacks, along with cookiejacking made possible by unencrypted networks and Firesheep. Even now we are seeing weaknesses at the highest echelons of security - hacked RSA databases and even HTTPS certificates.
Answering our question of what good security is clearly isn't easy. Of course, what if we assume that all security is broken? We would have to outlaw all hacking and seriously punish the offenders because there is nothing that can be done to lock up the system. This approach, however, is inherently flawed. For one, it is closely related to the drug war waged by the U.S. authorities, which has been astoundingly ineffective at stopping the drug trade. Not because it can't shut down drug-rings (it's very good at doing that), but simply because the business is so profitable that for every player you kill in the game, another one crops up to take their place. Lulzsec serves as a harbinger of that scenario, where hacking is cheap, and even if you throw everyone involved in jail, someone else will replace them.
However, even this scenario is being optimistic. If security is near impossible, computers become useless. The real world would turn into Hollywood, where electronics are easily bypassed. The problem is that if computer security is easily bypassed, people will stop using it. Online transactions die. The paper trail comes back. People refuse to put their personal details in anything that could be digitized. Everything that has enabled the technological explosion of today would get stuck in a tug-of-war between security and convenience. If history is anything to go by, the public would rather give up the last bits of their privacy just so they could use all the conveniences of electronics without having to worry about hackers. Suddenly we live in 1964.
This scenario may seem implausible to you because it is. Computer security can be effective, it simply needs to be done properly, which is not impossible. It may be difficult, but so is starting a successful company, and that doesn't seem to stop any of the entrepreneurs. The problem we face is that the average customer has no way of discerning good security from bad security. If they could, market pressures would force companies to adapt the best security possible, or customers would take their data elsewhere. Security is crap because no one knows what security is other then the security experts.
We have building inspectors and elevator certifications and health inspectors... why not security inspectors? It doesn't need to be government mandated, considering the government's track record, it might be a lot better if a private company or group provided the service, but somehow, there needs to be a way to measure security in a verifiable manner. There are two ways I know of to do this (there may be others) - from the inside, and from the outside. An inside inspection is more reliable when done properly, but more likely to be corrupted and gamed. An outside inspection, however, doesn't rely on the consent of a company to plaster a security rating on them. The downside is that an outside inspection requires pummeling the company's product blindly, which will only catch the really stupid mistakes, and not the dangerous middle-ground between really bad security and really good security.
I'm not pretending I know how to solve this problem. I don't, but I do know that someone needs to figure this out. If we are going to make any headway with security, the general public needs a friendly, easy, intuitive way to check the security rating of a company, instead of relying on the company's insistence that it uses a "very sophisticated security system". Only then will market pressures push for the resurgence of proper security.
June 8, 2011
My Mom Had a Heart Attack
She is fine and will make a full recovery.
About 3 weeks ago, on Thursday, May 19th, at approximately 6 PM, my mom went into ventricular fibrillation and collapsed while walking on a nearby trail. She was found by two walkers who called 911 and initiated CPR. After almost a half hour of CPR and 3 defibrillator attempts, she was stabilized and taken to the nearby hospital. She had no identification, so we didn't know about it until after 2 hours of failed searching, at which point my dad called the local hospital.
As I was taken to see her while in critical condition, we didn't know if she was going to survive, or if she did, if she would have serious brain damage. A lot of things went through my mind on that car ride, but the one that was the most striking was when I realized that my inability to achieve what I had been trying to do for so long could potentially mean the last thing my mom was mentally capable of processing would be a son who had simply tried to accomplish something. Who had tried very hard, but hadn't actually managed to do anything of significance. My life was simply a lot of determination, a lot of talk, a lot of failures, and no results. I was still in college, I still didn't have a company, I didn't even have a job, and I still hadn't brought any of my more spectacular ideas to fruition. I was almost 21 years old, my mom had almost died from a heart attack, and I hadn't actually done anything.
The next day my dad called "just about everyone" to tell them what was going on, which indirectly resulted in me being reunited with one of my old friends. Due to my mom's condition in the ICU, she had little to no short term memory, and so every day when I went to visit her I would tell her that my best friend from forever ago had visited, and every day (once the breathing tube was removed), she would react with surprise. She was very confused and kept asking about why she was in the hospital. It turns out this was a pretty good question.
They did a CT scan of her chest to see if she had any blockages or other potential threats to her heart, and discovered that her arteries were entirely devoid of plaque buildup, and she appeared to be almost perfect health, aside from the fact that her heart suddenly stopped working for what appeared to be no reason at all. The only connection we could find was that a similar event happened to my grandfather (her father) at almost the same age. While he also passed out, his episode was caused by atrial fibrillation. She has since had a miniature pacemaker of sorts installed that will automatically deliver a defibrillator shock if the event ever occurs again, but it raises questions about whether the condition is hereditary.
If this is some kind of strange genetic disorder, it carries the lovely news that even if I'm in perfect health in 30 years, my heart could get a random bad signal from my brain for absolutely no reason at all and I could keel over and die if no one happens to notice me pass out. Luckily I don't have to worry about that until I have kids in elementary school.
Thankfully my mom is back home and, aside from some minor lingering medications and precautions, has fully recovered. Unfortunately, I still haven't done anything.
About 3 weeks ago, on Thursday, May 19th, at approximately 6 PM, my mom went into ventricular fibrillation and collapsed while walking on a nearby trail. She was found by two walkers who called 911 and initiated CPR. After almost a half hour of CPR and 3 defibrillator attempts, she was stabilized and taken to the nearby hospital. She had no identification, so we didn't know about it until after 2 hours of failed searching, at which point my dad called the local hospital.
As I was taken to see her while in critical condition, we didn't know if she was going to survive, or if she did, if she would have serious brain damage. A lot of things went through my mind on that car ride, but the one that was the most striking was when I realized that my inability to achieve what I had been trying to do for so long could potentially mean the last thing my mom was mentally capable of processing would be a son who had simply tried to accomplish something. Who had tried very hard, but hadn't actually managed to do anything of significance. My life was simply a lot of determination, a lot of talk, a lot of failures, and no results. I was still in college, I still didn't have a company, I didn't even have a job, and I still hadn't brought any of my more spectacular ideas to fruition. I was almost 21 years old, my mom had almost died from a heart attack, and I hadn't actually done anything.
The next day my dad called "just about everyone" to tell them what was going on, which indirectly resulted in me being reunited with one of my old friends. Due to my mom's condition in the ICU, she had little to no short term memory, and so every day when I went to visit her I would tell her that my best friend from forever ago had visited, and every day (once the breathing tube was removed), she would react with surprise. She was very confused and kept asking about why she was in the hospital. It turns out this was a pretty good question.
They did a CT scan of her chest to see if she had any blockages or other potential threats to her heart, and discovered that her arteries were entirely devoid of plaque buildup, and she appeared to be almost perfect health, aside from the fact that her heart suddenly stopped working for what appeared to be no reason at all. The only connection we could find was that a similar event happened to my grandfather (her father) at almost the same age. While he also passed out, his episode was caused by atrial fibrillation. She has since had a miniature pacemaker of sorts installed that will automatically deliver a defibrillator shock if the event ever occurs again, but it raises questions about whether the condition is hereditary.
If this is some kind of strange genetic disorder, it carries the lovely news that even if I'm in perfect health in 30 years, my heart could get a random bad signal from my brain for absolutely no reason at all and I could keel over and die if no one happens to notice me pass out. Luckily I don't have to worry about that until I have kids in elementary school.
Thankfully my mom is back home and, aside from some minor lingering medications and precautions, has fully recovered. Unfortunately, I still haven't done anything.
Subscribe to:
Posts (Atom)