format

6.02.2017

C++ Run down Series: variables, types and casting

 

Abstract 

This week we will discuss variables, types and casting between types. We'll discuss how C++ sees variables, and what are types for. Variables are named positions of memory used by the programmer to hold values, during the lifetime of a process. The positions may be constant, and thus hold the same value throughout the process lifetime or be modifiable (thus the name variable).

Variables


In the previous post we looked at the requirements to write C++ software on all the major systems, using a simple "Hello world" as a motivation.
This week, we'll look into what makes a variables, types and conversions.
Let us start with variables; variables are nothing but named positions on virtual memory. These names allow us to know what goes where while the compiler will deal with the actual position in memory.
In most languages the usage of a variable is transparent. Let us look at an assignment operation:
 
<variable> = <expression>;

The left side of a assignment operation must be a variable. This is both expected and reasonable: if we want to save the result of a expression's computation, we'll save it onto a variable.
In typed programming languages, which means that each variable has a associated type, before we can use a variable we must declare it.
 
int iResult;

iResult = 1+1; 

In the above example, iResult is a name which is declared to be a integer position. When the compiler encounters this line, it'll reserve a virtual memory position to hold a single integer.
The second line is an assignment. The compiler's syntax checker will look at the line and decide if it is well-formed instruction: if all the symbols are recognized, if the line ends in with a semi-colon, if the right side is a valid expression and if the left side is a known name. If any of these conditions fail, the compilation will fail.

Types


Types are named concepts for variables. They specify how the compiler encodes instructions to deal with the memory holding the variable.
There are several types already defined on the language. There are LiteralTypes, which consist on bool, char, int, float, long and double.
Types that are not LiteralTypes, like user-defined types also exist. The standard defines several, for instance std::string, std::fstream, or std::iterator.

A program may use all available types to define new variables. It is possible also for a programmer to specify her own types.

Every variable must have an associated type; this information is used by the compiler to check the correctness of the program: you'll be warned if you try to save a char in a int, and the program's compilation would halt if you tried to save a byte in a string.

However, other conversions are possible. A char can be saved into a byte. A integer can be narrowed to a char. And a long can hold a int.
By and large, all LiteralTypes can be converted into another LiteralType. Let us call the preexistant variable value's type a "predecessor type" and the destination type the "successor type".
Whenever a predecessor type is stored with less bytes than the successor type, there is no cause of worry. However, when the successor type is itself stored with less bytes than the predecessor, we have a narrowing conversion. Narrowing conversions may yield unexpected results and in extreme cases, these conversions may be the source of very strange behavior in runtime. The most common cases of such problems are the conversions of floating point types (float, double) to other literals of lesser storage (byte, int). The most dramatic situation involving a casting problem was the explosion of the Ariene 5, on the 4ยบ of July in '95. A 64 bit floating point variable was narrowingly cast to a 16 bit integer, which led the guidance system astray.

Conversions


The conversions between types may be implicit or explicit. Implicit conversions are those which the compiler deduces the intervening types. The deduction takes into account the predecessor and successor types, and the compiler does its best to create code that does the conversion. If the compiler does not know of a way to do the conversion, the compiler stops the compilation process yielding an error.
An implicit conversion:
float a = 0.5f;

double b = a;


Explicit conversions are more programmer involved. The programmer specifies a conversion to be done through a casting operation.
An explicit casting operation:
 
int a = 1;

float b = (float) a;

In these operations, the type is specified before the predecessor variable appears. The (float) operator tells the compiler that a should be converted into a temporary float value and that value should be used to alter the memory that b holds.


There are other operators to handle type conversion. These are: dynamic_cast, reinterpret_cast, static_cast, and const_cast.
The general syntax is
<variable> = [dynamic,reinterpret,static,const]_cast< sucessor_type >( predecessor_value );

ex:
const float a = const_cast< const float >( 1 );


Each of these conversion primitives are similar to the explicit conversion above, however they have advantages over the explicit method. Most of the advantages are related to C++ virtual polymorphism but there three operators still relevant with LiteralTypes: const_cast, static_cast and reinterpret_cast which we'll talk about in another post.

If you liked the post, have any questions or suggestions, feel free to comment.
Next post, we'll deal with program control flow through conditionals.


5.28.2017

C++ Run Down Series: requirements and "hello world"

C++ Run Down Series: requirements and "hello world"

Abstract  

In this series I'll explore C++ language and how it applies to modern software development; this week I'll present the basis of the language and a few historic notes. This week we will look into what is necessary to compile a C++ "Hello world" program, and discuss one example.

What is C++ 

C++ is a language developed by Bjarne Stroustrup in 1979, that is one of the major computer programming languages in the world. Based on C, it has similar syntax with its predecessor and several other C-inspired languages.
However, unlike C, C++ is a object oriented language that supports also procedural programming and can be even adapted to a functional programming pattern, which means it is a overall specially suited language for many realms of software development from embedded system development through kernel development up to client applications.

The major users of C++ are performance-critical system developers, those who need the systems to respond in real (or near real time). Thus, we can find C++ being employed in financial trading where a single microsecond may impact the net result of a transaction (check this TED talk for a discussion on this subject; check this C++ API of a financial trader for its clients) to game industry where one has multiprocessor systems to compute and react to world changes, user input, task management all within a 30 fps limit.

These high demanding environments motivated the development of the language into a high level language with multi-paradigm support with concerns with performance.

For a wannabe game developer like myself, this is a must-learn, must-use language.
I've been fortunate to develop my skills in many projects, each with different challenges than the next, and I'll try to guide through an awesome, but also gigantic language; hopefully, by the end of this C++ course, you'll be able to write your own programs with C++, meaning that you'll know what to search for when looking to accomplish a task.

Requirements for following the series: a Linux or OSX machine (preferred) or a Windows box.
If you have Linux, I advise you to install your package manager's build tools. All distros package managers have a package that represent your distro's build tools. For most Debian-derived distros something like "apt-get install build-essential g++" would suffice.

For OS X, you'll need the XCode command line tools, and you'll be good to go. You can install the package through XCode, in the Preferences->Downloads, choosing Components, and clicking Install next to Command Line Tools. Alternatively you can use Terminal, and use the command string "
xcode-select --install".

If you use Windows you can choose one (or more) paths. The Microsoft's way would be to use Visual Studio. There was segment of the product called Visual Studio Express which was for non commercial usage. Nowadays you can get a Community Edition which is promoted as a full featured IDE.

If you use Windows but which to make cross compatible software from a free software tool set, I would recommend using MingW (with MSYS) and a open source IDE like CodeBlocks (I used this software for years, it is one hell of a IDE, props to the team). The MingW (with the MSYS) project allows you to use many open source tools like Make which are not native to Windows.

The other way you can go about this is using CygWin. CygWin project creates a Unix like environment on your Windows box, allowing you to create code that can be compiled on a CygWin-able Windows and a Unix machine.


If the difference between CygWin and MingW isn't clear, think about it this way: if you compile code with CygWin, you'll only be able to run the binary in a Windows with CygWin; if you compile code with MingW, all windows can run the binary. On the other hand, you can write fully POSIX compliant binaries with CygWin, while on MingW you'll have access to all POSIX support Microsoft mustered, and Win C++ API.

In doubt: CodeBlocks and MingW + MSYS because I can actually respond questions about those tools.

The rest of the series will present the code from a Linux's user perspective; if you have a Mac you'll probably be able to follow all the steps in order. If you have a Windows, CodeBlocks is straight forward.


So, the hello world example is overdue.

Open your terminal, and check if g++ is installed with

 
g++ --version

which should give the g++ version information if the installation was completed successfully. Open your tool of preference, either it being an IDE or a text editor (Linux users are encouraged to use vim or gvim). Lets begin. Our first program will be a "hello world" example. This is a simple, standard way, to approach a language. The main idea is to write a program that outputs a "Hello world" message.

#include <iostream>

int main() {
  std::cout << "Hello world" << std::endl;
  return 0;
}

The above C++ code has several interesting properties for such a simple program, each of which we'll explore in future posts of the series, as we'll dwell deeper into language.

In the first line, we are including part of the standard library of C++. This line gives the rest of the program access to the defined primitives in the iostream header.
The iostream header contains all the standard, cross-platform, definitions of Input and Output. It is this header file that declares the "std::cout" name we use a few lines down.

The "int main() {" line, declares and starts the definition of a function called "main". This function is the entry point of a program; execution starts at this function (unless otherwise configured) for all C and C++ programs.


The next line uses a name not declared on our program: std::cout. This names the "STandarD Console OUTput". The console is another name for the system's text terminal.
The name is also a object, a class instantiation -- we will explore object oriented programming at a later time -- which exports a way for the programmer to write to the console.
The "std::endl" is a cross platform name for the line terminator which is "\n" or "\r\n" depending on the system. This name also causes the program to write to the screen immediately .

The last instruction causes the control flow to terminate the program with the result 0.

Next week, we will start discussing variables, control flow conditionals and loops.
See you next week!

4.04.2015

fmmarques.make.v101 - Make system, Rule syntax, variables


Abstract This is the first installment of the make tutorial. The make tutorial is devised to help you learn about make, and to apply that knowledge to the automatization of the compilation process. In this installment we will focus on the make system, rule syntax, and defining and using variables.
I. Make system, rule syntax, variables
A. Make system
Make is a tool that allows the programmer to write rules, in order to accomplish tasks. As such, make can be used to automatize many tasks, but its main use is in programming projects that are deployed in source format.
Many open source projects take advantage of make, since it’s readily available on all GNU/Linux systems. Calling ”make”, will cause the make system to search for a Makefile file, in the directory. The first rule encountered will be handled as the default target. Make will try its best to accomplish every dependency of the target, and the target itself.
A Make rule target has a special characteristic: it represents a file. When a rule is applied, and a target is fulfilled then a file is traditionally created.
B. Rule syntax
A rule has a specific format, comprised of three elements: target, dependencies and commands. Lets see a example,
Listing 1.  Makefile
all: one
  echo ”I’m_executing_’all’_target.”

The result of the ”make” command will fail. When you run the command, make will try to create ”all” file. Its first action will be to check the ”one” dependency, and this is where our Makefile fails. ”one” file does not exist, do ”all” cannot be executed, and make complains it does not know how to create ”one”.
Lets make an addedum to the Makefile.
Listing 2.  Makefile
all: one
  echo ”I’m_executing_’all’_target.”

one:;

With the inclusion of the new rule, make now knows how to accomplish ”one”. If you execute ”make”, you’ll be greeted with
echo ”I’m_executing_’all’_target.”
I’m executing ’all’ target.
Note: You can silence an echo command with a @ before the command (i.e. @echo).

There is a interesting point to the file-as-target system followed by make. If you do not create a file, and both the ”all” and ”one” rules don’t, the rule will always execute.
Try the following
touch one all

If you try to execute make, you’ll be informed that all ’all’ is up to date. However if you do,
rm one all
touch all one

And try make again, now you’ll be again greeted by the ”I’m executing ’all’ target.” again. This is because the ’all’ file is just a little bit older than ’one’, and since make should update ’all’ when ’one’ is younger, ’make’ always tries to execute every command associated with the ’all’ target.
C. Variables
Variables are useful in Makefiles. By default every variable is a space separated list of textual elements. This means that when you set a variable to ”abc def” the variable has two elements: ”abc” and ”def”. There is a syntax for assigning value to variables, and for referencing the value within the variable. When used directly, the programmer is assigning a value to the variable, or defining it. When used with $(¡name¿) the programmer is using its variable.
There are also two flavors of variables in Makefile. The recursively expanded variable, which are defined with ’=’, and its evaluation is based on recursive expansion.
Listing 3.  Makefile
rof=$(t)
t=$(lol)
lol=Not laughing
all:; echo $(rof) # $(rof) is Not laughing”.

This flavor has two disavantages. One: it does not handle appending. Something like,
Listing 4.  Makefile
lol=$(lol) $(lol) # Infinite loop detected

Will cause infinite expansion. The second disavantage is with functions will be rerun every time the variable is evaluated. There are functions that will be studied in the next installments, like the wildcard that may cause unexpected results when ran.
Variables may be used both as targets or as dependencies. Example follows
Listing 5.  Makefile
DEPENDENCIES=main.c module.c
OBJECTS=main.o module.o
OUTPUT=main

$(OUTPUT): $(OBJECTS)
  echo ”I’m_executing_’all’_target.”

$(OUTPUT) is substitute for main. $(OBJECTS) is substituted for the ”main.o module.o”.
II. See also
A. Related posts
B. Bibliography

fmmarques.make.v102 - Implicit rules, extensions and wildcards.


Abstract In this installment, we will dwell into make and more advanced features. In the first installment, a simple overview was provided giving focus on rule formation, with target and dependencies thoroughly explained. Now, I’ll explain how to form more sofisticated rules, based on wider (or stricter) matching patterns.
I. Implicit rules, extensions and wildcards
A. Implicit rules
Implicit rules are rules well known by make. When make was written, C programming language was on its prime and the compilation process was well defined. GNU therefore decided to implicitly include that knowledge in make. When a rule states that a dependncy is a file with .o extension, this will cause the compilation of the same file with c extension. Listing 1.  hello.c
#include <stdio.h>

int main( int argc, char *argv[]) {
  printf(”Hello_world.”);
  return 0;
}
The above can be compiled with the following Makefile. Listing 2.  Makefile
hello: hello.o
    $(CC) -o hello hello.o
At this point, we have two files: hello.c and Makefile on the same directory. The execution of the command ”make” in the directory where hello.c (and Makefile) resides gives rise to the creation of hello.
How does this work? Make knows that in order to create the binary file hello, it must have a hello.o file available. We only created hello.c, and it is not even referenced in the Makefile, so what gives?
Make does know that when one compiles and does not link a source file, the file created is given the same basename with .o extension. With that knowledge, make extrapolates that since hello depends on hello.o, and since %.o files are compilations of respective %.c files (i.e. ”gcc -c hello.c” creates hello.o) there must be a hello.c file in the directory. If there is, timestamps are compared and if hello.c is newer than hello.o or hello.o does not exist, then the command ”$(CC) -c hello.c” command insues.
Note: $(CC) is a make variable standing for C compiler. You can do CC=gcc in the beginning of the Makefile.
B. Extensions
GNU make provides several builtin extensions, like basename or addprefix. These can ben proven useful in some situations. Continuing with our example, lets add two other C source files, Listing 3.  main.c
#include <stdio.h>

int hello();
int world();

int main(int argc, char *argv[]) {
  hello();
  world();
  return 0;
}
Listing 4.  world.c
#include <stdio.h>

int world() {
  printf(”world.”);
  return 0;
}
Lets also modify the hello.c file to contain the following code, Listing 5.  hello.c
#include <stdio.h>

int hello() {
  printf(”Hello”);
  return 0;
}
We have now three different C source files: hello.c, world.c and main.c. main.c contains the main function, and it is considered the main module. It also declares the signatures of both hello and world functions, which are defined within their respective modules.
Note: A function declaration is the simple statement of the function’s signature while a function definition contains the body of the function.
Now we must also update Makefile content to make sure the compilation process will include the new files, Listing 6.  Makefile
main: hello.o world.o main.o
    $(CC) -o main main.o hello.o main.o
Now ”make” will create ”main” which, when executed, will print out ”Hello world”.
Let us simplify the Makefile with extensions, if we can. Listing 7.  Makefile
DEP=hello world main
main: $(addsuffix .o,$(DEP))
    $(CC) -$@ $<
Note: addsuffix applies the first operand as a suffix to every element of the second operand.
Now, every time main is targeted, the list of names in DEP gets appended with a .o causing make to regenerate .o files as needed. This depends on the implicit rule that generates .o from .c files. The rule now can also be revamped to use the target and first dependency operators, $@ and $¡ respectively. See the first installment for more informations on these operators, rule syntax and variables.
As anyone who’ve ever delt with a large enough project can tell, this rules help with maintining the Makefile and the project itself; you online add (or remove terms) from the first line and the compilation process adapts to the newly added (or removed) items.
C. Wildcards
Wildcards are syntatic sugar to help the Makefile programmer to write smaller, more concise rules. Lets explore the running example, Listing 8.  Makefile
DEP=$(wildcard *.c)
main: $(patsubst \%.c,\%.o,$(DEP))
    $(CC) -$@ $<
Note: wildcard expands the pattern given to a list of existing filenames that correspond to the pattern.
Note: patsubst substitutes the explicit part of the name for another. % stands for whatever is not matched.
In this form, we automatically add all the C source files to the compilation process and create the main from these.
There is yet another flavor for wildcards in make, that are used for pattern matching. These will be covered on the next installment.
II. See also
A. Related posts
B. Bibliography