Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Output Questions - Part 1
C++

Output Questions - Part 1

Practice 15 C++ predict-the-output interview questions designed to test your understanding of language behavior and common traps.

1. What does this string comparison print?

#include <iostream>
#include <string>

int main() {
    std::string s1 = "hello";
    std::string s2 = "hello";
    const char *c1 = "hello";
    const char *c2 = "hello";

    std::cout << (s1 == s2) << "\n";
    std::cout << (c1 == c2) << "\n";
    return 0;
}

Output:

1
1

std::string == compares content — two equal strings are true. But c1 == c2 compares the pointer addresses of the two literals. Whether the compiler merges identical string literals is implementation-defined, so this is exactly the kind of comparison you must never rely on: on this compiler the literals are merged and the addresses are equal, giving 1 — but on another compiler the result could be 0. Never use == on const char* to compare text — use std::string or strcmp.

2. What does this integer division print?

#include <iostream>

int main() {
    std::cout << 7 / 2 << "\n";
    std::cout << -7 / 2 << "\n";
    std::cout << 7 % 3 << "\n";
    std::cout << -7 % 3 << "\n";
    return 0;
}

Output:

3
-3
1
-1

Since C++11, integer division truncates toward zero: 7 / 2 is 3, -7 / 2 is -3. The % result takes the sign of the dividend: 7 % 3 is 1, -7 % 3 is -1. This differs from Python’s floor division and is the standard C++ interview expectation.

3. What does this boolean output print?

#include <iostream>

int main() {
    bool a = true;
    bool b = false;

    std::cout << a << " " << b << "\n";
    std::cout << std::boolalpha;
    std::cout << a << " " << b << "\n";
    return 0;
}

Output:

1 0
true false

By default, std::ostream prints bool as 1/0. With the std::boolalpha manipulator, it prints true/false. The state change persists for the rest of the stream. This default 1/0 output is a frequent trick question.

4. What does this character literal print?

#include <iostream>

int main() {
    std::cout << sizeof('a') << "\n";
    std::cout << sizeof("hello") << "\n";
    return 0;
}

Output:

1
6

Unlike C, in C++ a character literal 'a' has type char, so sizeof('a') is 1 (in C it would be sizeof(int) = 4). "hello" is a const char[6] including the null terminator, so sizeof is 6. The C-vs-C++ sizeof('a') difference is a classic interview question.

5. What does this reference-vs-value print?

#include <iostream>

void set10(int x) { x = 10; }

void set10ref(int &x) { x = 10; }

int main() {
    int a = 1;
    int b = 1;

    set10(a);
    std::cout << a << " ";

    set10ref(b);
    std::cout << b << "\n";
    return 0;
}

Output:

1 10

Passing by value copies the argument, so set10(a) does not change a — prints 1. Passing by reference lets the function mutate the caller’s variable, so set10ref(b) changes b to 10. The & reference parameter is the C++ mechanism C emulates with pointers.

6. What does this default-argument virtual call print?

#include <iostream>

class Base {
public:
    virtual void show(int i = 10) {
        std::cout << "Base " << i << "\n";
    }
};

class Derived : public Base {
public:
    void show(int i = 20) override {
        std::cout << "Derived " << i << "\n";
    }
};

int main() {
    Base *p = new Derived();
    p->show();
    delete p;
    return 0;
}

Output:

Derived 10

Virtual dispatch calls Derived::show (dynamic type), but the default argument is chosen from the static type (Base), so i is 10. The result is the famous “Derived function, Base default” — Derived 10. Never use different defaults in overridden virtual functions.

7. What does this destructor order print?

#include <iostream>

struct A {
    ~A() { std::cout << "A "; }
};

struct B {
    ~B() { std::cout << "B "; }
};

int main() {
    A a;
    B b;
    std::cout << "end ";
    return 0;
}

Output:

end B A

Local objects are destroyed in reverse order of construction at the end of the block. a is constructed first, then b, so at scope exit b is destroyed first (prints B), then a (prints A). The "end " prints before any destructor. Destructor order is a staple C++ interview question.

8. What does this stack-vs-heap sizeof print?

#include <iostream>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *p = arr;

    std::cout << sizeof(arr) << "\n";
    std::cout << sizeof(p) << "\n";
    return 0;
}

Output:

20
8

sizeof(arr) is the full array: 5 * sizeof(int) = 20. sizeof(p) is the pointer size, 8 on a 64-bit platform. arr is the actual array, but when passed to a function or stored in a pointer it decays to int*, losing its size. This array-vs-pointer sizeof distinction is constantly tested.

9. What does this function-overload print?

#include <iostream>

void f(int) { std::cout << "int\n"; }
void f(double) { std::cout << "double\n"; }
void f(char) { std::cout << "char\n"; }

int main() {
    f(5);
    f(5.0);
    f('a');
    return 0;
}

Output:

int
double
char

Overload resolution picks the exact type match first. 5 is int, 5.0 is double, 'a' is char. The compiler prefers an exact match over a conversion, so each call reaches the right overload without ambiguity.

10. What does this integer-overload print?

#include <iostream>

void f(int) { std::cout << "int\n"; }
void f(double) { std::cout << "double\n"; }

int main() {
    f(3.14f);
    f('x');
    return 0;
}

Output:

double
int

3.14f is a float; neither overload matches exactly, so the compiler uses the promotion float → double. 'x' is a char, which promotes to int. When no exact match exists, integral promotions (charint, floatdouble) win over other conversions.

11. What does this increment-overload print?

#include <iostream>

int main() {
    int i = 5;

    std::cout << i++ << " ";
    std::cout << i << " ";
    std::cout << ++i << " ";
    std::cout << i << "\n";
    return 0;
}

Output:

5 6 7 7

i++ yields the old value 5 and then increments to 6. ++i increments to 7 and yields 7. The output is 5 6 7 7. Each expression is a separate statement here, so the order is fully well-defined.

12. What does this ternary print?

#include <iostream>

int main() {
    int x = 10;

    std::cout << (x > 5 ? "big" : "small") << "\n";
    std::cout << (x > 5 ? 100 : 200) << "\n";
    return 0;
}

Output:

big
100

The ternary cond ? a : b evaluates the condition and returns only the chosen branch. x > 5 is true, so it prints "big" and 100. The unselected branch is never evaluated — useful for lazy evaluation and avoiding side effects.

13. What does this const-correctness print?

#include <iostream>

int main() {
    const int x = 5;
    const int *p = &x;
    int y = 10;

    std::cout << *p << "\n";
    p = &y;
    std::cout << *p << "\n";
    return 0;
}

Output:

5
10

const int *p is a pointer to a const int — you cannot modify *p through it, but the pointer itself can be reassigned. So p = &y is legal and *p prints 10. A int *const (const pointer) would be the opposite: can’t reassign the pointer, but can modify the pointee.

14. What does this constructor-order print?

#include <iostream>

class Base {
public:
    Base() { std::cout << "Base "; }
    ~Base() { std::cout << "~Base "; }
};

class Derived : public Base {
public:
    Derived() { std::cout << "Derived "; }
    ~Derived() { std::cout << "~Derived "; }
};

int main() {
    Derived d;
    std::cout << "end ";
    return 0;
}

Output:

Base Derived end ~Derived ~Base

Construction is base first, then derived (base subobject initialized before the derived body runs). Destruction is the exact reverse: derived destructor first, then base. So we get Base Derived, then end, then ~Derived ~Base. This order is a guaranteed interview favorite.

15. What does this copy-construction print?

#include <iostream>

struct Vec {
    int x, y;
    Vec(int a, int b) : x(a), y(b) {}
};

int main() {
    Vec v1(3, 4);
    Vec v2 = v1;

    std::cout << v2.x << " " << v2.y << "\n";
    std::cout << (v1.x == v2.x) << "\n";
    return 0;
}

Output:

3 4
1

Vec v2 = v1 invokes the implicit copy constructor, which copies each member. v2 gets x = 3, y = 4, and the memberwise copy makes v1.x == v2.x true. For a simple aggregate like this the implicit copy is exactly what you’d expect.

My Private Notes

Notes are auto-saved locally to this device.