Are you ready to join majestic world of C and C++ of programming? Do you want to question your existence after few simple lines of C++?
If your answer is "Yeh!", “Yep“ or “Why not?“ - welcome to test your knowledge. You will be given multiple questions related to C or C++.
Please find correct answers and explanations in the end of the story. Good luck!
main;
What will happen if you try to compile this program using C compiler?
#include <iostream>
#include <unistd.h>
int main() {
for(auto i = 0; i < 1000; i++)
std::cout << "Hello world!\n";
fork();
}
How many lines will this program print?
#include <iostream>
int main() {
int array[] = { 1, 2, 3 };
std::cout << (4, (1, 2)[array]) << std::endl;
}
What will this program print?
#include <regex>
#include <iostream>
int main() {
std::regex re("(.*|.*)*O");
std::string str("0123456789");
std::cout << std::regex_match(str, re);
return 0;
}
How long will it take for this regular expression to match this input string?
#include <iostream>
struct Foo {
Foo() { std::cout << "Foo()\n"; }
Foo(Foo&&) { std::cout << "Foo(Foo&&)\n"; }
Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; }
};
int main() {
Foo f;
auto a = [f = std::move(f)]() {
return std::move(f);
};
Foo f2(a());
return 0;
}
The last line to be printed by this program is…
Foo()
Foo(Foo&&)
Foo(const Foo&)
#include <iostream>
int x = 0;
int bar(int(x));
int main() {
std::cout << bar;
}
What will this program print?
0
1
0x0
#include <iostream>
struct Foo {
Foo() { std::cout << "Foo()\n"; }
Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; }
Foo(int) { std::cout << "Foo(int)\n"; }
Foo(int, int) { std::cout << "Foo(int, int)\n"; }
Foo(const Foo&, int) { std::cout << "Foo(const Foo&, int)\n"; }
Foo(int, const Foo&) { std::cout << "Foo(int, const Foo&)\n"; }
};
void f(Foo) {}
struct Bar {
int i, j;
Bar() {
f(Foo(i, j));
f(Foo(i));
Foo(i, j);
Foo(i);
Foo(i, j);
}
};
int main() { Bar(); }
The last line to be printed by this program is…
Foo(int, int)
Foo(const Foo&, int)
Foo(int, const Foo&)
Foo(int)
I hope you will never find one of this peculiar snippets in the wild.
The smallest program
This is legal C code. It will compile and link successfully. It will crash if you try to run it. main;
- is global variable.
In C code you can omit a lot of things. For example you can omit the type of a global variable. By the default compiler will assume this type is an int
. Also there is no name mangling in C (unlike in C++), so when linking there is no way to distinguish variable main
from function main
.
Thus compiler will compile valid code, and linker will find something named main
in object file to link a program.
The fork
This is more POSIX feature rather than C or C++ feature. Implementations of IO operations use buffers for optimising performance. When you invoke fork
, the OS will create copy-on-write duplicate of process memory, the IO-buffers will likely duplicate as well and buffered strings likely will be printed more than 1000 times.
All you need is indices
Answer is 3
To understand this code lets take a closer look on how indices in C and C++ work: array[index]
, is the same as *(array + index)
, is the same as (index + array)
and the same as index[array
.
The second clue is operator,
. Its binary operator, it discards left argument and returns right argument.
Regular expressions
Its impossible to predict what will happen! The behaviour is up to implementation.
Im my environment this program raises the exception The complexity of an attempted match against a regular expression exceeded a pre-set level.
Other probable options are surprisingly long time or work as expected. It’s because there are two possible approaches to implement regular expressions.
First - transform regular expressions to finite automata O(n**2)
(n - length of pattern), match string O(m)
(m - length of string). This approach doesn’t support backtracking.
Second - greedy approach + DFS, supports backtracking but prone to exponential time complexity on certain patterns.
Moves and lambdas
Answer is Foo(const Foo&)
. Lambdas are immutable by the default, all values captured into lambda with []
are implicitly const
. This unlocks idempotent behaviour for lambdas.
When you move f
you create const Foo&&
. const Foo&&
is a weird type, thus compiler just copies Foo
There are two ways to fix this:
Create mutable lambda
auto a = [f = std::move(f)]() mutable {
return std::move(f);
};
Declare constructor Foo(const Foo&&)
X and bar
The program will print 1
.
int bar(int(x));
— is weird way to declare function, it is equal to int bar(int x);
.
If you confused with type cast, int bar((int(x)));
- this is type cast.
Than we try to implicitly cast function address tobool
, the result of such cast is always true
.
Functionbar()
has never been used, thats allow us to dodge unreferenced symbol error while linking.
Constructors
The last line is Foo(const Foo&, int)
.
Foo(i)
is variable declaration, the same as Foo i
. Thus class member under the name of i
is hidden in this scope.