C/C++ Resources and FAQ
1.46K subscribers
1 photo
2 files
23 links
This is a sub channel for the C/C++ forum (https://t.me/programminginc). Here you can find links to various useful resources (including book recommendations and video resources) for C/C++ programmers and also answers to frequently asked C/C++ questions.
Download Telegram
Official C standards (Draft copies)

C89

C99

C11

C17

C23
👍5
Official C++ Standards (Draft Copies)

C++11

C++14

C++17

C++20

C++23 (In progress)
👍7
C++ Guidelines - This site lists guidelines for C++ Programmers. Both Bjarne Stroustrup and Herb Sutter monitor the guidelines here to ensure they reflect the current standards on best programming practices.

CPP Best Practices - This site is maintained by Jason Turner (one of the cppcast podcast host) and perfectly compliments the site above.
👍2
C++ Documentation - CppReference

Only quote this site in your answers. Quotes from other sites like CProgramming or CPlusPLus are not authentic and don't reflect the C++ standard or Modern Programming guidelines. Accordingly, any links to such sites will be deleted.
👍4
Best IDEs for C/C++ Development

When a user asks for a recommendation for the best development environment on a platform, they are usually concerned about just the coding editor. But a development environment is much more than that. It includes at the minimum a powerful code editor, a debugger, a compiler, a linker and build tools to manage your source code and artifacts.

A software like Visual Studio combines all of them in one package. But some others like to mix and match. Keeping in mind that most of the users who ask this question are beginners, here are a few recommendations.

Before I list down the IDEs to use, let me list the ones that you should avoid.

Turbo C and Turbo C++

Dev C++

Both these are relics of the past and were/are no longer suitable for C and C++ development. Please avoid them at all costs and switch to the more modern development environments listed below.


Windows

Microsoft Visual Studio (Latest Community Edition). The Community Edition is free for use. The Professional and the Enterprise edition come with more bells and whistles that are geared towards a team of developers and you will have to pay for them. For most individuals, the Community Edition should be perfect.

CLion - This is arguably as good as Visual Studio. It however is free only if you are a student. You need to provide them with your school/college email id to be able to use their IDE for free. This software package comes bundled with the build tools like compiler et al. You will not have to install them separately

For Windows it is recommended to stick with Visual Studio or CLion. If you are familiar with alternate installation of compilation tools then other IDEs like Code Blocks or an editor like VS Code are good enough

For Windows the best compilation platform is the one offered by Microsoft itself and it comes bundled with the Visual Studio package installer or the CLion installer. You can install the compilation platform alone as well without the Visual Studio editor/debugger

Some users prefer to install GCC or Clang on their Windows machines. To do that you will have to use MSYS2 (if you are from a Linux env and prefer the entire Linux build platform). Cygwin and MinGW are not recommended as they lag behind MSYS2 on the latest version of the build tools. Unless you want to be stuck with an old version of GCC or Clang, use MSYS2.

Update - Winlibs offers a complete standalone build environment that features GCC or Clang for Windows. This is a better alternative to MSYS2 even.

Once you install the required environment, you can change your Visual Studio settings or the CLion settings to point to these installations.

Visual Studio Code

This unlike Visual Studio is just a code editor (packed with some useful features). People who don't want a bulky software installation like Visual Studio, usually prefer Code. But remember that this is just an editor. You must install the build platform following the steps mentioned earlier and configure Code Editor's settings to point to the installation environment.

Code Blocks

This is just like Visual Studio Code. You install Code Blocks and then change its settings to point to the compiler, debugger et al that you want to use and you are good to go.

There are other IDEs like QTCreator etc etc which deserve special mention. But they are best avoided by beginners because they enforce certain rules on developers which are best avoided as a beginner.

Linux

Most Linux installations have GCC/G++/bintools et al pre-installed. If yours doesn't, check your distro's documentation to see how you can install these packages on your machine. If you prefer the LLVM environment, then check your distro's package manager documentation to see how you can install LLVM Clang.

The best code editors (IDEs) for Linux are

CLion

Visual Studio Code

QTCreator (Not for beginners)

Atom

ViM

emacs

MacOS

XCode (Usually is pre-installed & recommended)

CLion

Visual Studio Code

(Section In Progress. Suggestions and instructions from Mac users are welcome)
👍9
Channel name was changed to «C/C++ Resources and FAQ»
Common Idioms and Patterns in C++

C++ Patterns

C++ Idioms

More C++ Idioms
👍2
C/C++ Open Source Libraries

A list of open source C++ libraries

A list of open source C libraries

Another list for C++ libraries (May overlap with the previous one)

How to Build X from scratch - A collection of tutorials on how you can build from scratch something like an emulator, game engine, a container like Docker etc etc
👍1
Member generation.png
273.1 KB
When are the special member functions (default constructor, copy/move constructor, copy/move assignment operators and destructor) generated?

The rules for generation of these special member functions is tabularized in the attached image.
👍1
How to compare floating point numbers in C++?

Comparison of floating point numbers is a tricky business as floating point numbers are not represented exactly by your computer. An approximation is what is stored. So you can't compare floating point numbers directly using == operator. This would result in the wrong answer.

To understand how floating point numbers are stored and why comparing floating point numbers using == would fail, read this article.

Assuming you have read the article above, this is how you would compare floating point numbers for equality in C++.


template<typename T>
bool fequal(T x, T y, int N)
{
    T diff = std::abs(x-y);
    T tolerance = N*std::numeric_limits::epsilon();
    return (diff <= tolerance*std::abs(x) && diff <= tolerance*std::abs(y));
}

N here represents the approximate number of rounding errors you expect before you compare the floating point numbers. This can be 1 for most use cases.

The code above can be translated to C by defining epsilon to be a very small floating point number (how small depends on how accurate or the precision you desire for comparisons). The rest of the code is straightforward to implement.
👍3
Difference between keywords struct and class

Members of a class defined with the keyword class are private by default. Members of a class defined with the keyword struct are public by default.

In the absence of an access-specifier for a base class, public is assumed when the class is declared with the keyword struct  and private is assumed when the class is declared using keyword class.

The keyword class can be used to declare template parameters while the keyword struct cannot be used to do this.

Advice : In general it is preferable to explicitly specify the access specifiers for the members of your class/struct instead of relying on the default.

Likewise it is  preferred to make your base classes explicitly public, protected or private rather than relying on the default behavior depending on whether your class is declared using keyword struct or class.

This specifies your intentions clearly.

Now it brings us to the question of situations when a particular keyword should be preferred over the other.

You should use struct when you want to declare classes that are meant to behave like values i.e. classes which have very few methods and has public data. You should use the keyword class otherwise.
👍2
What is Undefined Behavior?

(https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior)

Undefined behavior is one of those aspects of the C and C++ language that can be surprising to programmers coming from other languages (other languages try to hide it better). Basically, it is possible to write C++ programs that do not behave in a predictable way, even though many C++ compilers will not report any errors in the program!

Let's look at a classic example:

#include <iostream>
int main() {
char* p = "hello!\n"; // yes I know, deprecated conversion
p[0] = 'y';
p[5] = 'w';
std::cout << p;
}

The variable p points to the string literal "hello!\n", and the two assignments below try to modify that string literal. What does this program do?

According to section 2.14.5 paragraph 11 of the C++ standard, it invokes undefined behavior:

The effect of attempting to modify a string literal is undefined.

I can hear people screaming "But wait, I can compile this no problem and get the output yellow" or "What do you mean undefined, string literals are stored in read-only memory, so the first assignment attempt results in a core dump". This is exactly the problem with undefined behavior. Basically, the standard allows anything to happen once you invoke undefined behavior (even nasal demons). If there is a "correct" behavior according to your mental model of the language, that model is simply wrong; The C++ standard has the only vote, period.

Other examples of undefined behavior include accessing an array beyond its bounds, dereferencing the null pointer, accessing objects after their lifetime ended or writing allegedly clever expressions like i++ + ++i.

Section 1.9 of the C++ standard also mentions undefined behavior's two less dangerous brothers, unspecified behavior and implementation-defined behavior:

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine.

Certain aspects and operations of the abstract machine are described in
this International Standard as implementation-defined (for example, sizeof(int)). These constitute the parameters of the abstract machine. Each implementation shall include documentation describing its characteristics and behavior in these respects.

Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified (for example, order of evaluation of arguments to a function). Where possible, this International Standard defines a set of allowable behaviors. These define the nondeterministic aspects of the abstract machine.

Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer). [ Note: this International Standard imposes no requirements on the behavior of programs that contain undefined behavior. —end note ]


Specifically, section 1.3.24 states:

Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

--(continued)
👍4
(continued) To understand the difference between Unspecified behavior and implementation defined behavior, you just have to know that the compiler has at times various (limited) ways it can execute your code. During the times where it can choose between any of these ways (because the standard imposes no specific choice and doesn't require the compiler to do so either), then the behavior is Unspecified.

During those times where the standard says that the compiler implementation can choose any of the ways but must also document which way it chooses, then the behavior is Implementation Defined.

For ex:

int a = f(x) + g(y);

Here the compiler may decide to evaluate g(y) before f(x) or vice-versa. The standard imposes no requirements on which argument to operator+ is evaluated first and it also doesn't require the compiler to document which operand it evaluated first. So this is an example of Unspecified Behavior.

If on the other hand, the standard required the compiler to document which argument it evaluated first, then Compiler A can choose to evaluate the first argument f(x) first always and compiler B can choose to evaluate g(y), the second operand first always. Both of these are acceptable according to the standard. This would be an example of Implementation Defined Behavior.

According to the C++ standard, the order of evaluation of arguments is Unspecified Behavior.
👍4
What is the difference between public, protected and private inheritance in C++?

Let's consider a class Base and a class Child that inherits from Base.

If the inheritance is public, everything that is aware of Base and Child is also aware that Child inherits from Base.

If the inheritance is protected, only Child, and its children, are aware that they inherit from Base.

If the inheritance is private, no one other than Child is aware of the inheritance.

Example:


class A
{
public:
int x;
protected:
int y;
private:
int z;
};

class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};

class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};

class D : private A // 'private' is default for classes
{
// x is private
// y is private
// z is not accessible from D
};
👍3
I know what lvalues and rvalues are. But what do people mean when they say xvalues, glvalues and prvalues?

(From Stackoverflow)

An lvalue (so-called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. [Example: If E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the result of calling a function whose return type is an lvalue reference is an lvalue.]

An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references. [Example: The result of calling a function whose return type is an rvalue reference is an xvalue.]

A glvalue (“generalized” lvalue) is an lvalue or an xvalue.

An rvalue (so-called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object or subobject thereof, or a value that is not associated with an object.

A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [Example: The result of calling a function whose return type is not a reference is a prvalue]
👍2
What is Copy Elision and Return Value Optimization?

(From Stackoverflow)

Copy elision is an optimization implemented by most compilers to prevent extra (potentially expensive) copies in certain situations. It makes returning by value or pass-by-value feasible in practice (restrictions apply).

It's the only form of optimization that elides (ha!) the as-if rule - copy elision can be applied even if copying/moving the object has side-effects.

The following example taken from Wikipedia:

struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
return C();
}

int main() {
std::cout << "Hello World!\n";
C obj = f();
}

Depending on the compiler & settings, the following outputs are all valid:

Hello World!
A copy was made.
A copy was made.


Hello World!
A copy was made.


Hello World!


This also means fewer objects can be created, so you also can't rely on a specific number of destructors being called. You shouldn't have critical logic inside copy/move-constructors or destructors, as you can't rely on them being called.

If a call to a copy or move constructor is elided, that constructor must still exist and must be accessible. This ensures that copy elision does not allow copying objects which are not normally copyable, e.g. because they have a private or deleted copy/move constructor.

C++17: As of C++17, Copy Elision is guaranteed when an object is returned directly:

struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
return C(); //Definitely performs copy elision
}
C g() {
C c;
return c; //Maybe performs copy elision
}

int main() {
std::cout << "Hello World!\n";
C obj = f(); //Copy constructor isn't called
}

(Named) Return value optimization is a common form of copy elision. It refers to the situation where an object returned by value from a method has its copy elided. The example set forth in the standard illustrates named return value optimization, since the object is named.

class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
Thing f() {
Thing t;
return t;
}
Thing t2 = f();


Regular return value optimization occurs when a temporary is returned:

class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
Thing f() {
return Thing();
}
Thing t2 = f();
👍4
What is external linkage and internal linkage?

When you write an implementation file (.cpp, .cxx, etc) your compiler generates a translation unit. This is the source file from your implementation plus all the headers you #included in it.

Internal linkage refers to everything only in scope of a translation unit.

External linkage refers to things that exist beyond a particular translation unit. In other words, accessible through the whole program, which is the combination of all translation units (or object files).

You can explicitly control the linkage of a symbol by using the extern and static keywords. If the linkage is not specified then the default linkage is extern (external linkage) for non-const symbols and static (internal linkage) for const symbols.

// In namespace scope or global scope.
int i; // extern by default

const int ci; // static by default

inline const int ci; // external linkage since C++17

extern const int eci; // explicitly extern

static int si; // explicitly static

// The same goes for functions (but there are no const functions).

int f(); // extern by default

static int sf(); // explicitly static

Note that instead of using static (internal linkage), it is better to use anonymous namespaces into which you can also put classes. Though they allow extern linkage, anonymous namespaces are unreachable from other translation units, making linkage effectively static.

namespace {
int i; // extern by default but unreachable from other translation units

class C; // extern by default but unreachable from other translation units
}
👍2
What is span and when should we use it?

(From Stackoverflow)

A span<T> introduced in C++20 is:

A very lightweight abstraction of a contiguous sequence of values of type T somewhere in memory.
Basically a struct { T * ptr; std::size_t length; } with a bunch of convenience methods. It is similar to a slice or a fat pointer in Rust.

A non-owning type (i.e. a "reference-type" rather than a "value type"): It never allocates nor deallocates anything and does not keep smart pointers alive.

It was formerly known as an array_view and even earlier as array_ref.

When should I use it?

First, when not to use it:

Don't use it in code that could just take any pair of start & end iterators, like std::sort, std::find_if, std::copy and all of those super-generic templated functions.

Don't use it if you have a standard library container (or a Boost container etc.) which you know is the right fit for your code. It's not intended to supplant any of them.

Now for when to actually use it:

Use span<T> (respectively, span<const T>) instead of a free-standing T* (respectively const T*) when the allocated length or size also matter. So, replace functions like:

void read_into(int* buffer, size_t buffer_size);

with:

void read_into(span<int> buffer);

Why should I use it? Why is it a good thing?

Oh, spans are awesome! Using a span...

- means that you can work with that pointer+length / start+end pointer combination like you would with a fancy, pimped-out standard library container, e.g.:

for (auto& x : my_span) { /* do stuff */ }

std::find_if(my_span.cbegin(), my_span.cend(), some_predicate);

std::ranges::find_if(my_span, some_predicate);

... but with absolutely none of the overhead most container classes incur.

- lets the compiler do more work for you sometimes. For example, this:

int buffer[BUFFER_SIZE];
read_into(buffer, BUFFER_SIZE);

becomes this:

int buffer[BUFFER_SIZE]; read_into(buffer);

which will do what you would want it to do.

- is the reasonable alternative to passing const vector<T>& to functions when you expect your data to be contiguous in memory. No more getting scolded by high-and-mighty C++ gurus!

- facilitates static analysis, so the compiler might be able to help you catch silly bugs.

- allows for debug-compilation instrumentation for runtime bounds-checking (i.e. span's methods will have some bounds-checking code within #ifndef NDEBUG ... #endif)

- indicates that your code (that's using the span) doesn't own the pointed-to memory.

There's even more motivation for using spans, which you could find in the C++ core guidelines - but you catch the drift.
👍4