Category Archives: The Basics

Operators

We’ve learned that programming is essentially either processing data or moving them around, so we ‘operate’ on data. To do flow control, we need to construct conditions, thus we do logic operations too. In C programming, we use operators do all that.

An operator is a symbol that operates on value or variable, or on condition.  For example, we already know that ‘+’ is a operator to perform addition.

C language provides a wide range of operators to support different operation needs. Let’s learn a few of the basic ones here.

Arithmetic Operators

These are operators we use for math.
+ addition
subtraction
* multiplication
/ division
% modular division

Modular division gives us the remainder after the division, for example,

9 % 2 = 1
13 % 10 = 3

The ‘-‘ can also be used on a value or variable to negate it, for example, if x = 5, then -x equals to -5.

‘++’ and ‘–‘  are called increment and decrement operators, they can be applied to a variable. The ‘++’ is equivalent to +1, and ‘–‘ to -1. So if x = 1; then after ++x or x++, x becomes 2. You may wonder what is the difference between ‘x++’ and ‘++x’ then?  We will learn it later on, but that would be something fun for a research.

When we do math, it usually takes the following form,

x = y + z;

Sometime though, we want to operate on the same variable, like the following,

/* add 10 to current value of x and assign the value back to x
x = x + 10;

For that, we can use a simpler form,

x += 10;

Relational Operators

These are operators we use for conditions.

== equal to
> greater than
< less than
>= greater than or equal to
<= less than or equal to
!= not equal to

They operate on two variables or a variable and a value, we then use the result for decision making, or flow control as we just learned. For example,

if ( a != b) { /* do something here if a is not equal to b */ }

Logical Operators

These are operators for, well, logic, as the title indicates. We use them to combine condition expressions.

&& Logical AND
|| Logical OR
! Logical NOT

For example,

if ( (a > 3) && (a < 10) ) {
        /* do something here only if
             a is greater than 3, and
             a is less than 10
        */
}
if (  ! (a == 3)  ) {
        /* do something here only if NOT a == 3,
              so this is a different way of saying (a != 3)
        */
}

Note that it is always a good habit to use parenthesis around the conditions that we do logic operations on, to make the logic obvious.

There are other operators, which we will learn later, for now these should be sufficient for us to do some interesting math.

Next, let’s look at how we write our code to make that interesting math more manageable …

Flow Control

We’ve learned that the instructions are executed one after the other from the beginning to the end within a function. Quite often though, we actually need more than that. For example, we might need to do certain things only under certain conditions, or we need to do certain things more than one time before continuing with something else. We basically need to control the flow of our program, or in other words, making decisions based on conditions.

C language provides a few different flow control or decision making methods. Before explaining them, let’s first introduce the ‘block’ and ‘condition’.

block: a group of instructions that are enclosed in a pair of curly braces. Instructions in a block are executed together, variable definition within a block is also allowed, which we’ll learn later.

Any number of instructions can be grouped together  by having ‘{‘ and ‘}’ around them, anywhere. But normally it only makes sense to group instructions together for given conditions. For example, if this condition is true, then do these block of instructions.

A block looks like the following,

condition: a test expression that is evaluated to either true or false. For example, ‘3 > 1′ is a true condition, and ‘2 == 3′ is false one (note the double ‘=’ sign, since a single ‘=’ is used for value assignment). It is not very useful to have constant condition like that though, usually the test expression has variable in it, so we test whether the variable value meets the condition or not at our program run time. For example, ‘x > 2′ will be true only if the value of variable x is greater than 2.

 With that, here comes the flow control methods …

1. if … else

if ( conditions ) blockA else blockB

if ‘conditions’ are true, then blockA will be executed, otherwise instructions in blockB will be executed, for example,

The else part is optional, for example,

if … else can be concatenated and cascaded, to however many levels needed, for example,

As shown above, the position of the ‘{‘ or ‘}’ does not really matter, but it is important to make sure they always come as a pair.

2. switch … case

switch ( variable or expression ) {case ( constant_1 ) : instructions; break; case ( constant_2 ) : instructions; break; default : instructions; break; }

Depending on the value of ‘variable or expression’, only the instructions under the matching ‘case’ are executed.

The ‘break‘ instruction ends the entire switch block. Without that, instructions from the following ‘case’ will be executed, till it hits a ‘break‘ statement.

For example,

 3. goto

goto label;

Any time when there is a ‘goto label’ statement, program will unconditionally go to the instruction pointed to by ‘label’. For example,

Note that in above code, the instruction between the ‘goto’ statement and label ‘next_st’ will never get executed. Thus ‘goto’ is usually paired with ‘if‘ or other conditional statement.

Please keep in mind that we should always try to minimize of the use of ‘goto’ statement, as it breaks the normal flow of the program and makes it hard to follow and understand the program.

4. while … do

This comes in two forms,

while ( conditions block

do block while ( conditions );

The first form executes the block while conditions are true, the next block first executes the block once, then continue to execute block while conditions are true. For example,

or,

Exercise: are the output from above two different  from each other? what if we change line #1 to ‘x = 5’?

5. for loop

for ( initial instructions; conditions; update instructions ) block

The initial instructions (separated by ,) are executed once and once only at the beginning of loop.

Then the conditions are tested, if false, the loop is terminated, otherwise the the block of instructions are executed.

Then the update instructions are executed.

The above repeats until the loop terminates, for example,

 

Note that ‘ii++’ is the same as ‘ii = ii + 1′.

It is ok to have all fields of for loop empty, in which case it becomes an infinite loop. In real programming though, you probably want some condition to terminate the loop. For example,

 6. break … continue

Within while or for loop, ‘break‘ statement will immediately terminate the loop, ‘continue‘ statement will immediately skip the rest of the instructions in the loop and jumps to the beginning of the loop. For example,

Exercise: how many times the “I am here” is printed above?

We learned all the basic flow controls above, there’s one last statement, ‘return‘.

return: immediately returns from and terminates function.

The return statement can be anywhere in the function, after that instruction, the entire function terminates and the program flow goes back to the caller of the function. If we return from the ‘main’ function, the entire program terminates.

So we ‘return’ here …

Data Types and Variable

When programming, we always work with data, either processing them by doing math, or moving them around. Most of the time programming job requires that we do both.

For example, if we write a pong game, we first need to ‘draw’ a ball, imagine that a ball is made of lots of small dots (we usually can them pixels), we’ll need some math to determine where each dot needs to be drawn at. Then we want to move the ball around,  we’ll probably just move the pixel data around.

So what is data?

In the simplest form, let’s think data as ‘number’.

Even for just number, there are different ‘types’ of them. For example, integer, fractional, there is also the difference between positive and negative.

The data needs to be stored somewhere, thus the size of the data matters. If we know the number is going to be small, we do not want to reserve large storage space for it. On the other hand, if the number can grow to be really big, we need to make sure we have enough space for it. For example, in the pong game above, we probably only need a small number to record the level the player is at, but would need a big number to record player’s current score.

To manage all different types of data, C language defines data types, some of the basic types are,

  • char: character, range from -128 to 127
  • short: short integer, range from -32768 to 32767
  • int: integer, range from -32768 to 32767, or -2,147,483,648 to 2,147,483,647 (we call this platform dependent, which we’ll learn later, for now it is safe to assume int has a range of the latter)
  • long: long integer, range from -2,147,483,648 to 2,147,483,647

Each of the above integer types also has a corresponding ‘unsigned’ type, thus,

  • unsigned char: from 0 to 256
  • unsigned short: from 0 to 65536
  • unsigned int: from 0 to  4, 294,967,296
  • unsigned long: from 0 to  4, 294,967,296

For fractional (or floating point) number,

  • float: 6 decimal places
  • double: 16 decimal places
  • long double:19 decimal places

I’ll leave the actual range of these types for your research, at this point it is enough to know that these are good for fractional math, such as 3.14 * 0.96.

There is also a special type called ‘void’, which we’ll learn more about it later on.

  • void: special type to indicate no data available.

As mentioned above, data needs to be stored somewhere, we call that storage ‘variable’,

  • variable: the name to the storage place that holds the data

To define a ‘variable’, we use the following syntax,

<type> <variable name>

Once the variable is defined, we can then store data there, please keep in mind that the data stored must match the variable type.

Here’s a simple data type example,

A few things to note,

  1. variable can only be accessed after they are defined.
  2. variable can be used to store data, and storing data must be on the right hand. In other words, the following would be incorrect,
    234567 = iy;
  3. variable only holds one copy of data, old data gets lost when new data is stored. For example, add the following in line #12, and see what happens, ix = 999;
  4. printf can print out formatted data, “%d” and “%f” above are format specifier. Research yourself to see what more printf can do.
  5. note line #4 and line #8, they are there to help us and others to understand what the program does. They’ll be ignored by the compiler. It is always a good habit to write comments when programming. C language comments can be wrapped around by /* and */.

So much for the data types and variables, let’s move on …

Introduction

As we’ve learned, when programming, we basically provide a collection of instructions for computer to follow and execute. The programming language is designed to make those instructions easier to understand and remember, for us programmers, and provide flexibility to do many different things, also in different ways. Most importantly, programming language is designed to be consistent, once the program is written, there will never be ambiguity in how the program will behave. This is unlike the language we speak or write in, the same combination of words may mean totally different thing, depending on who says them when, and sometime in what tone.

C language is no exception, it has strict grammar that we must follow. Let’s look at the very first hello program we wrote,

C program instructions is organized in block called ‘function’,

function: is an execution block, the instructions in the function will be executed from start to end.

Function takes the following format,

<return_value_type> <function_name> ( parameters) { instructions; }

The <return_value> is something this function returns once it completes all its instructions, we’ll learn more on this later.

On line #3 above,  we can see that the return value is ‘int’, and the function name is ‘main’. Also this function takes two parameters, enclosed in a parenthesis ‘()’. we’ll explain what parameter means later.

Function then starts with a ‘{‘, with instructions in the middle, and ends with a ‘}’. At the end of each instruction, there must be a ‘;’.

White space or tab will be ignored, and can be used to format the code so it looks neat and easier to read. There are cases where space and tab are significant, we’ll learn all that later.

Within a function, we can call other functions, for example, we call the ‘printf’ function in line #4.

When programming we write our own functions, and also call to functions that are written by someone else, from a library. For the latter, we’ll need to include the library ‘header’.  In line #1, we include the standard I/O library header, since we use ‘printf’, a function from that library.

For the function we write, we can give it any name we like, as long as the name is allowed by C language grammar, for example, function name has to start with an alphabetical letter or _, and can not have space in between etc. There’s a few exceptions,

  • some name is reserved by C language, for example, you can not name a function as ‘int’
  • the same name can only be used once in one file

And there is a requirement for the very first function, it must be named as ‘main’, since this will be the main entry point to the program. No matter how big our program grows to, it always starts from this ‘main’ function.

Here’s another simple program, this time we write a new function to print out more info,

In above example, the ‘hey’ function takes no parameters, thus it has an empty ‘()’, and it has no return value either, thus the ‘void’ return type.

So ‘main’ function calls our ‘hey’ function twice, one after the other other, and in between we print a separator line.

Next, let’s look at more language basics …