You are currently browsing the archives for the C/C++ Programming category.

Bitesize Modern C++: Uniform initialization

July 30th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

C++98 has a frustratingly large number of ways of initialising an object.

image

(Note: not all these initialisations may be valid at the same time, or at all. We’re interested in the syntax here, not the semantics of the class X)

One of the design goals in C++11 was uniform initialisation syntax. That is, wherever possible, to use a consistent syntax for initialising any object. The aim was to make the language more consistent, therefore easier to learn (for beginners), and leading to less time spent debugging.

To that end they added brace-initialisation to the language.

As the name would suggest, brace-initialisation uses braces ({}) to enclose initialiser values. So extending the above examples:

image

There are a couple of highlights from the above code:

Integer i is default-initialised (with the value 0). This is equivalent to C++03’s (much more confusing):

image

x1 is explicitly default-constructed. This alleviates the ‘classic’ mistake made by almost all C++ programmers at some point in their career:

image

By extension, this also alleviates C++’s Most Vexing Parse as well. For those not familiar with it, here it is:

image

Most programmers read this as "create an object, adt, and initialise it with a temporary object, ADT()". Your compiler, however, following the C++ parsing rules, reads it as "adt is a function declaration for a function returning an ADT object, and taking a (pointer to) a function with zero parameters, returning an ADT object."

With brace-initialisation, this problem goes away:

image

The compiler cannot parse the above except as "create an object, adt, and initialise it with a temporary object, ADT{}"

The uniform initialisation syntax goal means that brace-initialisation can be used anywhere an object must be initialised. This includes the member initialisation list:

image

In C++98 programmers had the capability to initialise static member variables as part of the class declaration. C++11 extends this to allow default-initialisation of non-static class members. The code:

image

Can be re-written as:

image

The member initialiser code ensures that the member variable will always have a default value, even if it is not explicitly initialised in a member initialiser list. For the example above we have told the compiler to provide the default constructor; which does nothing.

When we create object adt1 the (compiler-supplied) default constructor is called. The member initialisers in the class-definition ensure that the members of adt1 are initialised.

Having the initialisers visible at point-of-instantiation gives the compiler the opportunity to optimise (away) constructor calls and create the object in-situ.

 

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++: using aliases

July 16th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

In a C++ program it is common to create type aliases using typedef. A type alias is not a new type, simply a new name for an existing declaration. Used carefully, typedef can improve the readability and maintainability of code – particularly when dealing with complex declarations.

image

In C++11 typedef can be replaced with a using-alias. This performs the same function as a typedef; although the syntax is (arguably) more readable. A using-alias can be used wherever a typedef could be used.

image

Using-aliases have the advantage that they can also be templates, allowing a partial substitution of template parameters.

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++: nullptr

July 2nd, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

What’s the value of a null pointer?

  • 0
  • NULL
  • NUL

No doubt you’ve been involved in the (always heated) discussions about which is the correct one (By the way, if you said NUL you need to take yourself to one side and give yourself a stern talking to).

The arguments tend to go something like this:

  • 0 is the only ‘well-known’ value a pointer can be set to that can be checked.
  • NULL is more explicit than just writing zero (even though it is just a macro definition wrapper)

The problem with using 0 or NULL is that they are, in fact, integers and that can lead to unexpected behaviours when function overloading occurs.

image

Based on what we’ve just discussed it should be pretty straightforward to see that the int overload will be called. (This rather weakens the argument that NULL is more explicit – explicitly confusing in this case!)

It gets worse: Implementations are free to define NULL as any integer type they like. In a 32-bit system it might seem reasonable to set NULL to the same size as a pointer:

image

Sadly, this just adds confusion to our code:

image

In case you’re a C programmer who’s looked at this (and is feeling pretty smug at the moment):

image

Unfortunately this won’t compile, because a void* cannot be implicitly converted to an int, long or int* (or any other type) in C++.

In C++11 the answer to the question of the value of a pointer is much more simple: it is always nullptr

In our code, using nullptr instead of NULL gives the results we expect

image

nullptr is a keyword that represents any ‘empty’ pointer (and also any pointer-like objects; for example smart pointers) A nullptr is not an integer type, or implicitly convertible to one (it’s actually of type nullptr_t).  However, it is implicitly convertable to bool; and to maintain backward compatibility the following code will work as expected:

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++: enum class

June 18th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

Enumerated types in C++ give a trivial simulation of symbolic types – that is, objects whose instances have unique, human-readable values. In C++ enumerations are essentially named integers that are either assigned values implicitly by the compiler or explicitly by the programmer (or a combination of both)

C++ enum types inherit their semantics from C with some additions:

  • enum objects are now first-class types
  • enums may be implicitly converted to integers; but the reverse is not true

image

Another characteristic illustrated in the above code is the need for all enumerated symbols to be (globally) unique. This can be both frustrating and difficult to maintain for larger systems.

C++11’s enumeration classes provide strongly-typed enumerations.

An enum class, unlike the C++98 enum does not export its enumerator names into its enclosing scope, meaning different enum class objects can have the same enumerator value, without causing a name issue.

Also, enum class values cannot be implicitly converted to integers.

image

One of the more confusing aspects of C++98 enums was their size – although the type of an enum was defined (int) its size was implementation defined and required only to be a type big enough to hold the largest enumerated value. This means that an enumeration could be 8, 16, 32 or even 64 bits in size; and could change if new enum values were specified. This could (and probably has!) cause alignment issues in embedded systems.

We can now specify the underlying type of the enumeration (as long as it’s an integer type). The default is integer; as with C++98.

image

If the enum class type is to be used as a forward reference you can (must) provide the underlying type as part of the declaration.

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++ : static_assert

June 4th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

C’s assert library is a useful tool for catching invalid invariants (conditions that must hold true in order for your system to operate as specified) in your program. The big problem with assert is that it’s a run-time check; in many cases the best you can do  to recover from an assert failure is restart the system or put it into a quiescent state.

In a lot of cases the (faulty) invariants could be detected at compile-time but in C++98 there was no mechanism for doing so. The pre-processor has an assert-like mechanism – #error – but the pre-processor has no knowledge of your C++ code so it cannot evaluate program invariants.

In C++11 a compile-time assert mechanism was added: static_assert.

static_assert acts like run-time assert except that the checked-condition must be a constant-expression (that is, an expression that can be evaluated at compile-time); the checked-condition must be a boolean expression, or an expression that can be converted to a boolean.

image

The message string must be a string literal.  It cannot be a (compile-time) computed value (ignoring pre-processor stringification).

From C++17 the message will be optional.

 

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++ : constexpr

May 21st, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

A constant expression is an expression that can be evaluated at compile-time. The const qualifier gives a weak guarantee of a constant expression – a const-qualified type may not be changed after initialisation but that does not guarantee it will be initialised at compile-time. For example:

image

C++11 introduces a strong form of constant expression, constexpr, which also expands the capabilities of compile-time evaluation.

constexpr objects

A constexpr variable is essentially the same as qualifying the type as const with the additional requirement that its initialiser(s) must be known at compile-time. Any object type that could be made const can be made a constexpr object.  As expected, the object must be initialised on definition.  Note that literals are, by definition, constant expressions.

image

Since constexpr types have their value known at compile-time they can be placed in read-only memory; and, for built-in types (and provided you don’t take their address) the compiler doesn’t even have to store the object. We’ll look at user-defined (class)types in a moment.

constexpr functions

So far, so what?

The real power of constant expressions comes from the fact that not only objects but functions may be qualified as constexpr.

A constexpr function is one that may be evaluated at compile-time; and hence used in the definition of other constant expressions:

image

Of course, there are some limitations with constexpr functions:

  • They must have exactly one return statement
  • They cannot have local variables
  • They cannot have conditional expressions
  • They cannot throw exceptions
  • They cannot include a goto statement
  • All parameters must be (capable of being) constexpr objects

Put simply, in order to be a constexpr function everything the function needs to be computed must be known at compile-time. Making a function a constant expression implies it is inline.

(Note: C++14 relaxes some of these requirements with respect to local variables and conditionals).

Marking a function as a constexpr doesn’t limit it to only be usable at compile-time. They may still be used at run time:

image

ROM-able types

The use of constexpr for functions extends to member functions, too. Marking a member function as a constexpr implicitly makes it a const function, meaning it cannot change any of the attributes of the class.

This is also true of constructors. Making a class’s constructor a constexpr allows objects of that type to themselves be constexpr objects.

image

Since everything required to construct the Rommable object is known at compile-time it can be constructed in read-only memory.

In order to be truly ROM-able there are some additional requirements we must satisfy (over and above the requirements for a constexpr function):

  • The class cannot have any virtual functions (virtual functions cannot be constant expressions)
  • The class cannot have a virtual base class
  • All base classes and all const members must be initialised by the constructor

 

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++ : auto

May 8th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

C++ is a statically-typed language, that is, you must explicitly declare the type of every object before use. The type of an object specifies

  • The amount of memory occupied
  • How the memory (bits) is interpreted
  • The operations allowable on the object

An object’s type is fixed at declaration – unless the programmer chooses to circumvent the type system using a cast.

Often for C++ objects specifying the type can be onerous:

image

C++11 allows automatic type-deduction to simplify the creation and maintenance of code.

The auto keyword has been appropriated from C (where it was a storage specifier indicating a local – ‘automatic’ – variable) that is almost never used.  From C++11 onwards auto now means ‘deduce the type of an object’

Let’s start with some simple (but not particularly useful) examples.

image

The compiler uses the type of the initialiser to establish the type of the new object. Note, the object still has a definitive (and fixed) type. Type-deduction does not lead to ‘duck typing’.

(As an aside, one might reasonably argue that there is very little benefit in auto-deducing built-in types; and, in fact, could even be less explicit to the reader)

To use auto the compiler must have the information to deduce the type (and therefore allocate memory). Therefore, there are some (obvious?) limitations to where auto can be used:

image

The mechanism used by the compiler for type-deduction is the same one used to deduce parameter types for template functions. Because of this, the object-type deduced for an auto object may not be exactly what the programmer expects.

The rules are as follows:

  • The deduced type will be a new object.
  • If the initialiser is a reference-to-object, the reference is ignored (since a reference is just an alias for an object).
  • Any const-volatile (cv)-qualifiers on the initialiser are ignored (since the cv-qualifiers are a property of the initialiser, not the new object).
  • Arrays are degenerated into pointer types.

image

We can cv-qualify the deduced type separately, if required. The cv-qualifiers are applied to the new object – after its type has been deduced.

image

If we reference-qualify the auto-deduced type the rules change:

  • The deduced type will now be a reference the initialiser object.
  • Any cv-qualifiers of the initialiser will be maintained on the deduced type (since a reference cannot be less restrictive than its referent; although it can be more restrictive).
  • If the initialiser is an array the deduced type is a reference-to-array type, not a pointer.

image

Returning to our original example, we can simplify the code (considerably) with the use of auto.

image

Additionally, the use of auto allows us a degree of flexibility in our code for future modifications:

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++

May 7th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

The C++11 standard marked a fundamental change to the C++ language. A range of new language constructs and library features were added and, as a result, new idioms were developed. Bjarne Stroustrup, originator of C++, referred to it as “feeling like a completely new language”.

In 2014 a revision of the standard was released with refinements to C++11 features and some new constructs, designed to improve the usability of the language; another revision is planned for 2017.

Traditionally, C++ programmers refer to their language version by the standard release year (so, C++98, C++03) but, as C++11 marked such a fundamental shift in the programming style of C++ (and as revisions are coming out more frequently) people are starting to refer to C++ post-2011 as ‘Modern C++’

In the embedded world Modern C++ has had comparatively little take-up, possibly due to a lack of embedded compiler support. Slowly, though, this is beginning to change.

There is a huge amount of material available on Modern C++. It has been explored, examined and dissected by experts for nearly five year. However, for the C++ programmer just starting to transition to Modern C++ a lot of this material can be somewhat overwhelming. For many it can be difficult to find a simple place just to start.

And that’s the idea behind these articles.

We wanted to present simple introductions to the new features in Modern C++ – ones that are useful for programmers currently using C++98. These are not the big, headline features – lambda expressions, move semantics, etc. – but the ‘little’ additions that can make you more productive and your programs more elegant and maintainable.

The other thing we wanted to avoid was TMI – Too Much Information. These articles are not meant to be definitive; they don’t explore every last quirk and corner-case. You won’t be an expert after reading these articles. Their purpose is simply to get you started; to give you a jumping-off place for all the excellent, detailed information out there.

For those who can’t wait the full set of articles will be available to download as a PDF

Enjoy!

The Rule of Zero

January 15th, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

In a previous article – ”The Rule of the Big Four (and a half)” we looked at resource management policies in C++.

Resource management is the general term for using the mechanisms in C++ to ensure that resources – files, dynamic memory, sockets, mutexes, etc – have their lifetimes automatically controlled so as to prevent resource leaks, deadlocks, etc. C++ refers to these mechanisms as RAII/RDID ( “Resource Acquisition Is Initialisation / Resource Destruction is Deletion”)

In this article we’ll have a look at a complementary guideline to help simplify your application code, without risking resource management issues – The Rule of Zero.

Read more »

The Rule of The Big Four (and a half) – Move Semantics and Resource Management

January 1st, 2015

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.

Latest posts by Glennan Carnie (see all)

In the previous article we looked at the issues of resource management in C++ and introduced “The Rule of The Big Three (and a half)”. In this article we’ll extend this concept by looking at the idea of move semantics, a feature introduced in C++11. Move semantics mean we’ll have to extend our rule to “The Rule of The Big Five” or, perhaps more correctly, “The Rule of The Big Four (and a half)”.

Read more »

%d bloggers like this: