Hidden Gems of C and C++ That You Probably Don’t Know

C++ is a great language with too many features. I have experienced multiple “WTF” moments throughout my career as a C++ developer. In this story, you will find the most entertaining aspects of C and C++ programming condensed in the form of tests. No way you can get more than a couple of questions right.


This content originally appeared on HackerNoon and was authored by Ilia

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!

1. The smallest program

main;

\ What will happen if you try to compile this program using C compiler?

  1. will not compile
  2. will compile, will not link
  3. will compile and will link

2. The fork

#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?

  1. 1000
  2. less than 1000
  3. more than 1000

3. All you need is indices

#include <iostream>

int main()  {
    int array[] = { 1, 2, 3 };
    std::cout << (4, (1, 2)[array]) << std::endl;
}

\ What will this program print?

  1. 1
  2. 2
  3. 3
  4. 4
  5. will not compile
  6. undefined

4. Regular expressions

#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?

\

  1. 1 ms
  2. 1 sec
  3. 1 min
  4. 1 hour
  5. 1 year
  6. forever

5. Moves and lambdas

#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…

\

  1. Foo()
  2. Foo(Foo&&)
  3. Foo(const Foo&)

6. X and bar

#include <iostream>

int x = 0;
int bar(int(x));

int main() {
    std::cout << bar;
}

\ What will this program print?

  1. 0
  2. 1
  3. 0x0
  4. will not compile
  5. will not link

7. Constructors

#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…

  1. Foo(int, int)
  2. Foo(const Foo&, int)
  3. Foo(int, const Foo&)
  4. Foo(int)

Instead of conclusion

I hope you will never find one of this peculiar snippets in the wild.

Answers

  1. 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.

    \

  2. 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.

    \

  3. 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. \n

    The second clue is operator,. Its binary operator, it discards left argument and returns right argument.

    \

  4. 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.

    \

  5. 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:

    \

  6. Create mutable lambda

      auto a = [f = std::move(f)]() mutable {
              return std::move(f);
          };
    

    \

  7. Declare constructor Foo(const Foo&&)

    \

  8. 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);. \n

    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.

    \

  9. 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.

\


This content originally appeared on HackerNoon and was authored by Ilia


Print Share Comment Cite Upload Translate Updates
APA

Ilia | Sciencx (2024-08-09T13:46:20+00:00) Hidden Gems of C and C++ That You Probably Don’t Know. Retrieved from https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/

MLA
" » Hidden Gems of C and C++ That You Probably Don’t Know." Ilia | Sciencx - Friday August 9, 2024, https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/
HARVARD
Ilia | Sciencx Friday August 9, 2024 » Hidden Gems of C and C++ That You Probably Don’t Know., viewed ,<https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/>
VANCOUVER
Ilia | Sciencx - » Hidden Gems of C and C++ That You Probably Don’t Know. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/
CHICAGO
" » Hidden Gems of C and C++ That You Probably Don’t Know." Ilia | Sciencx - Accessed . https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/
IEEE
" » Hidden Gems of C and C++ That You Probably Don’t Know." Ilia | Sciencx [Online]. Available: https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/. [Accessed: ]
rf:citation
» Hidden Gems of C and C++ That You Probably Don’t Know | Ilia | Sciencx | https://www.scien.cx/2024/08/09/hidden-gems-of-c-and-c-that-you-probably-dont-know/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.