Category Archives: C Language

Array

We have learned the basic data type and we can use that to define any variable, the defined variable will then carry and manage a copy of data of that given type. For example,

int ijk;

 That will define a variable ‘ijk’ of type ‘int’, we can assign any integer to ‘ijk’ any time, ‘ijk’ will then carry that integer from that point on.

Sometime we need to work on more than one instance of data, and they all have the same type. For example, let’s say we design a game that can support up to 50 players, we need to record the score for each player. We could define 50 variables like the following,

int score1, score2, … score50;

That may work,  but has at least two obvious issues, we have to separately operate on each different variable, and it becomes not manageable if we need to support 5000 players.

C language has a data structure defined to handle that,

array: a data structure that can store a fixed number of elements of the same type

 An array can be defined like the following,

<type> array-name [ number-of-elements ];

For example,

int scores[5000];

This defines an array called ‘scores’ that has 5000 elements of integers. Each element of the array can be accessed by its index, starting from zero, for example,

scores[0] is the very first element, and scores[4999] is the last element.

With array, we can easily display all the scores using a loop,

It is very important to note that,

  • array index starts from 0, not 1
  • you can never write beyond the array length, for example, the following will create a serious error and cause the program to crash,

scores[5000] = 123;

An array can be defined initialized or uninitialized, for example, the above scores array is defined uninitialized, we did not give an initial value to each element. We can also give array initial values at definition,

int xyz[5] = {1, 2, 3, 4, 5};

This will define an array of 5 integers, with xyz[0] of value 1, xyz[1] of value 2 and so on.

Array index has to be an integer of value greater than or equal to zero, thus xyz[-1] is incorrect, since there is not element of array that has an index value of -1.

That’s all for Array, with one exception, we haven’t talked about how to pass array around, as a function parameter or return value, which we will learn later on. For now, it is good enough for us to just use array directly …

Function

We briefly introduced function as a building block to C programming, let’s take a closer look at it, as we will use it for almost all the programs we write.

We already know that program is a collection of statements, so why do we need function at all? Or, maybe we need just the main function itself, why do we ever need to write our own function?

We need function for code reusing,

– function is a good way of reusing common code, so we do not need to write the same thing over and over

– function gives us the power to use someone else’s code as well, even if the code is from someone we do not know

– function allows multiple developers to work together, each developer can work on one part of the program

Let’s look at a simple example, the following program prints the last digit of a few numbers,

Basically we do a modular division of 10, then print the value, and we are doing the same thing 4 times. How about we write a function to print the last digit of any number, then just call that function?

The above program can be rewritten the following way,

As introduced before, function takes the following format,

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

The printLastDigit function we wrote above takes only one parameter, the ‘number’ we want to print the last digit of. Each time when we call that function, we pass in a different number for the function to print.

In above example, we only print the last digit, once we pass in the number, that is all we need that function to do. We do not expect anything returned from it, that is why the return type is ‘void’.

Let’s change the requirement a little bit, after the last digit is printed, we also return it, so the caller can do something with it. Let’s write the program that prints the last digit of a few numbers, then we sum up all the last digits, and print the last digit of the sum value.

We can modify the above program to the following,

The ‘getAndPrintLastDigit’ function returns the last digit after the printing. At line #11 we initialize the sum as zero, then we add each return value to it, after line #16, we have the sum of all the last digits of the 4 numbers we have above.

At line #18, we print the last digit of sum itself, and ignore the return value, since we do not have any further use of it.

Note a few things in above program,

– when calling the function, we can pass in either a constant value, for example line #13 through #16, or pass in a variable as we do in line #18.

– when the function is called, the parameter will have the value we pass in. For example, the ‘number’ parameter variable will have the value of 3456 when line #15 is calling the function. The ‘number’ parameter variable will have the value of sum when line #18 is calling the function.

– Each time the function is called, the caller must supply the parameter, but can choose to ignore the return value. For example, at line #18, we call the function but do not collect the return value.

If you wonder what the ‘static’ keyword does in above example, it is a way of saying that the function we wrote can only be called from within the same file. So if our program has more than one files, the static function can not be called from any other files. Why we add that limit? we will learn more on that later, but it is enough to know for now that it is a good practice to use ‘static’ keyword for any local function we write.

We now have a new weapon to simplify our code and get more done …

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 …