Most programming languages have a concept known as "type," implemented via a "type system."
When a programmer writes a program, he will generally declare a set of variables and then write some source code that tells the computer to do something with the variables. Each variable, when declared, is associated with a type, such as integer, byte, or string. The type determines how the compiler will interpret the source code that works with the variables, which will determine what sort of machine code to emit during compilation.
For example, in c#, if I want to add or subtract two numbers I might write:
int a = 2;
int b = 2;
int c = a + b;
int d = a - b;
In this code, I have told c# that I want four memory locations, and I want them treated as integers. On the third line, I can use the +
operator on a
and b
because addition is allowed for integers. And on the fourth line I can use -
.
If I wanted to work with strings, I might write this instead:
string a = "2";
string b = "2";
string c = a + b;
string d = a - b; //Error
In this example, I have told c# to set up four memory locations and treat them like strings. On line 3 I can add them together because addition is valid for strings (it will concatenate them). But on the fourth line the compiler will tell me I have made a mistake, because subtraction is not allowed for strings, since it is not exactly clear what it would do if it were allowed.
Similarly there are data types for dates, times, floating point numbers, and complex structures. In addition, a programmer can often define his own types, such as objects, which can be programmed to represent business concepts, database connections, or other more advanced structures, all of which require a memory location for storage, but have different rules for how to read those memory locations.
In some rare cases you can copy data of one type to a variable of another type. This is generally not allowed in "type safe" languages because the data could be misinterpreted. But in languages like assembly and c, you can do it, and you will usually need to be very careful not to cause problems.
Now what about code? Well, code is just another memory location, and it too gets a name ("symbol"), known as the entry point:
static void main()
{
int a = 2;
int b = 2;
int c = a + b;
int d = a - b;
}
In the above example, I declare a memory location with an entry point named "main." This memory location will contain the instructions to reserve memory for a
, b
, c
, and d
, and it will contain instructions to set them to 2 and to do the math. When I write source code that calls main
, the compiler will emit machine-readable code that points the instruction pointer at the entry point main
, where it will execute the instructions. Thus there is never any mixing between code and data, and the computer (hopefully) will never try to execute a number or try to do math on code.