БлогNot. Можно ли в C++... или каверзные вопросы по языку

Помощь дата->рейтинг Поиск Почта RSS канал Статистика nickolay.info Домой

Можно ли в C++... или каверзные вопросы по языку

сейчас в списке: 21 вопрос Проверьте себя, хорошо ли Вы понимаете этот замечательный язык.

Ответы даны сразу же по ссылкам оглавления, но лучше сначала подумать.

Вероятно, список будет пополняться и послужит хорошим дополнением к "Типичным ошибкам начинающего разработчика на C++".

Можно из этого сделать и какой-нибудь тест - на сколько вопросов вы смогли ответить или хотя бы рассуждали в правильном направлении?

Все коды проверялись в консоли Visual Studio 2015 или близких версий.

Оглавление

Вычисления, арифметика

Можно ли в C++ сравнить значения 2 переменных без использования оператора сравнения (==)?

Можно ли в C++ поменять местами значения 2 переменных без использования третьей переменной или арифметических операций?

Можно ли в C++ сложить 2 числа, не используя операцию сложения?

Можно ли в C++ умножать или делить целое значение на степени двойки, не используя операций "*" или "/"?

Можно ли в C++ найти максимум или минимум из двух целочисленных значений, не используя условий или циклов?

Как узнать максимальное значение для беззнакового целого типа?

Можно ли в C++ выполнить обе ветви условного оператора "если-то-иначе"?

Можно ли в C++ найти знак числа без использования любого (бинарного или тернарного) условного оператора?

Можно ли в C++ напечатать натуральный ряд чисел, не используя цикла или рекурсии?

Можно ли в C++ напечатать ряд натуральных чисел 1,2,...,N, не используя ни одной точки с запятой?

Можно ли в C++ найти сумму всех цифр числа одним оператором?

Функции, namespace

Можно ли в C++ вызвать необъявленную функцию?

Можно ли в C++ одновременно использовать одноимённые локальную и глобальную переменные?

Можно ли в C++ вызвать функцию слева от знака "="?

Можно ли в C++ из пустой функции main что-нибудь вывести в консоль?

Классы

Можно ли в C++ получить доступ к приватным свойствам класса без использования методов-членов или функций-друзей класса?

Можно ли в C++ сделать класс, объекты которого можно будет создавать только динамически?

Можно ли в C++ сделать класс, объекты которого наоборот можно будет создавать только в стеке, но не динамически в куче?

Разное

Можно ли в C++ проверить порядок байтов (big-endian/little-endian) компьютера?

Можно ли в C++ писать URL-адреса прямо в тексте программы?

Можно ли в C++ из пользовательской программы завершить работу системы?

Ответы на вопросы
Можно ли в C++ вызвать необъявленную функцию?

Только если скомпилировать файл типа .c, но не .cpp, например, делать так было можно в "чистом" C:

#include <cstdio>

void f(); /* функция описана без аргументов! */

int main() {
 f(2); /* компилируется в файле .c, но не .cpp */
 getchar();
 return 0;
}

void f(int x) { /* реализация функции имеет аргумент */
 printf ("%d", x);
}
Можно ли в C++ одновременно использовать одноимённые локальную и глобальную переменные?

Да. Оператор области видимости ::

#include <iostream>
using namespace std;

int x = 5;  //глобальная

int main() {
 int x = 10; //локальная
 cout << "global x = " << ::x << endl;
 cout << "local x = " << x;
 cin.get(); return 0;
}
Можно ли в C++ вызвать функцию слева от знака "="?

Да, например, так:

#include <iostream>
using namespace std;

int &fun() {
 static int x; //с не-статической переменной м.б. небезопасно
 return x;
}

int main() {
 fun() = 10;
 cout << fun() << endl; //10
 cin.get(); return 0;
}
Можно ли в C++ получить доступ к приватным свойствам класса без использования методов-членов или функций-друзей класса?

Ага :) Указатели-то на что?

#include <iostream>
using namespace std;

class Test {
private:
 int data;
public:
 Test() { data = 0; }
 int getData() { return data; }
};

int main() {
 Test t;
 int *ptr = (int*)&t;
 *ptr = 10; //косвенно пишем в свойство data... приём опасный, но работает не хуже лома
 cout << t.getData(); //приватное свойство было изменено. Вот и вся инкапсуляция :)
 cin.get(); return 0;
}
Можно ли в C++ сделать класс, объекты которого можно будет создавать только динамически?

Угу. Сделав деструктор приватным, мы лишим компилятор возможности удалять созданные в стеке объекты, на что он будет ругаться ошибкой компиляции.

А для удаления динамических объектов кучи можно предусмотреть отдельную функцию-друг класса. Это будет платой за "защиту от стека".

#include <iostream>
using namespace std;

class Test {
private:
 ~Test() { cout << "Destroying Object\n"; }
public:
 Test() { cout << "Object Created\n"; }
 friend void destructTest (Test *);
};

void destructTest(Test* ptr) {
 delete ptr;
 cout << "Object Destroyed\n";
}

int main() {
 //Test t1; //теперь это вызовет ошибку компиляции

 Test *t2 = new Test(); //Всё хорошо
 destructTest (t2);
 
 cin.get(); return 0;
}
Можно ли в C++ сделать класс, объекты которого наоборот можно будет создавать только в стеке, но не динамически в куче?

Да. В противоположность предыдущему пункту, можно определить в классе приватный оператор new.

#include <iostream>
using namespace std;

class Test {
 void* operator new (size_t size){};
 int x;
public:
 Test(int x) { this->x = x; }
 void show() { cout << x << endl; }
 ~Test() { }
};

int main() {
 //Test* t1= new Test(1); //А теперь нельзя вот так
 
 Test t2(2); t2.show(); //Всё работает
 cin.get(); return 0;
}
Можно ли в C++ из пустой функции main что-нибудь вывести в консоль?

Да. Скажем, создав глобальный объект класса, который выводит что-то в консоль из конструктора.

#include <iostream>
using namespace std;

class Test {
public:
 Test() { cout << "Hello, world!"; }
} test;

void main() {}

Также класс можно заменить структурой или просто глобальной переменной:

#include <cstdio>

int var = printf ("Hello, world!");
void main() {}
Можно ли в C++ напечатать натуральный ряд чисел, не используя цикла или рекурсии?

Да. Можно использовать шаблоны класса и статические функции.

#include <iostream>
using namespace std;

template <int N> class Printer {
public:
 static void print()  {
  Printer<N - 1>::print();  //Это - не рекурсия, а вызов статического метода!
  cout << N << endl;
 }
};

template <> class Printer<1> {
public:
 static void print()  {
  cout << 1 << endl;
 }
};

int main() {
 const int N = 1000;
 Printer<N>::print();
 cin.get(); return 0;
}

...или просто массив объектов класса и статическую переменную.

#include<iostream>
using namespace std;

class Printer {
public:
 static int a;
 Printer() {
  cout << a++ << endl;
 }
};

int Printer::a = 1;

int main() {
 const int N = 1000;
 Printer obj[N];
 cin.get(); return 0;
}
Можно ли в C++ найти сумму всех цифр числа одним оператором?

Да, если это оператор цикла for

#include <iostream>
using namespace std;

int main() {
 int n = 6789, sum;
 for (sum = 0; n > 0; sum += n % 10, n /= 10); //один оператор
 cout << sum;
 cin.get(); return 0;
}

Можно ли в C++ писать URL-адреса прямо в тексте программы?

Да. Полную ссылку, которая начинается с названия протокола, можно вставить в текст программы без каких-либо символов-ограничителей.

#include <iostream>
using namespace std;

int main() {
http://www.disney.com

cout << "Hello, world!";
cin.get(); return 0;
}

Просто http: воспринимается как метка, а всё, что за символами // - как комментарий :)

Можно ли в C++ поменять местами значения 2 переменных без использования третьей переменной или арифметических операций?

Да. Есть ещё побитовые операции и операция следования (запятая).

#include <iostream>
using namespace std;

int main() {
 int x = -5, y = 10;
 (x ^= y), (y ^= x), (x ^= y);
 cout << x << " " << y;
 cin.get(); return 0;
}
Можно ли в C++ из пользовательской программы завершить работу системы?

Да, поскольку доступна функция system. Наверное, не буду выполнять этот код :)

#include <cstdlib>
using namespace std;

int main() {
 char *cmd = "c:\\windows\\system32\\shutdown /i"; //В кавычках - команда для Windows
 //или "shutdown -P now" для Linux
 system(cmd);
 return 0;
}

На самом деле, современные ОС попросят подтвердить действие.

Можно ли в C++ сравнить значения 2 переменных без использования оператора сравнения (==)?

Да. Побитовое исключающее "или".

#include <iostream>
using namespace std;

int main() {
 int x = 10, y = 10;
 cout << x << (!(x ^ y) ? "==" : "!=") << y;
 cin.get(); return 0;
}
Можно ли в C++ напечатать ряд натуральных чисел 1,2,...,N, не используя ни одной точки с запятой?

Рекурсивный вызов функции main позволяет решить эту задачу, например, так:

#include <iostream>
using namespace std;
int N = 10;

int main() {
 static int x = 1;
 if (cout << x << " " && x++ < N && main()) {} //точки с запятой при решении задачи нет!
 //cin.get(); //иначе придётся нажить Enter 10 раз, рекурсия же :)
 return 0;
}
Можно ли в C++ найти максимум или минимум из двух целочисленных значений, не используя условий или циклов?

Да.

#include <iostream>
using namespace std;

int main() {
 int a = -10, b = 10;
 cout << endl << "Max=" << ((a + b) + abs(a - b)) / 2;
 cout << endl << "Min=" << ((a + b) - abs(a - b)) / 2;
 cin.get(); return 0;
}
Можно ли в C++ сложить 2 числа, не используя операцию сложения?

Да. Есть же вычитание :)

#include <iostream>
using namespace std;

int main() {
 double a = -3.5;
 double b = 2.8;
 double sum = -(-a - b);
 cout << endl << "Sum=" << sum;
 cin.get(); return 0;
}
Можно ли в C++ выполнить обе ветви условного оператора "если-то-иначе"?

Да.

#include <iostream>
using namespace std;

int main() {
 if (!(cout << " 1 ")) { 
  cout << " 1 "; //Проверьте в отладчике, это тоже выполняется
 }
 else { cout << " 2 "; }
 cin.get(); return 0;
}
Можно ли в C++ умножать или делить целое значение на степени двойки, не используя операций "*" или "/"?

Это можно делать в любом языке, где есть побитовый сдвиг. Умножению значения x на 2, например, соответствует операция x << 1, а делению y на 4 - действие y >> 4. Не путайте операторы побитового арифметического сдвига с переопределёнными в некоторых классах (например, в классах поточного ввода-вывода) операторами вставки << и извлечения >>.

#include<iostream>
using namespace std;

int main() {
 int x = 4, y = -8;
 x = x << 1; //4*2==8
 y = y >> 2; //-8/4==-2
 cout << x << " " << y;
 cin.get(); return 0;
}
Можно ли в C++ проверить порядок байтов (big-endian/little-endian) компьютера?

Для многобайтовых величин имеет значение, в каком порядке хранятся байты числа.

Порядок байтов бывает big-endian (от старшего к младшему) и little-endian (от младшего к старшему).

Например, десятичное число 10000 равно 0x2710 в 16-ричном виде и "естественном" представлении big-endian, а в little-endian это будет 0x1027. Именно так может храниться значение на линейке процессоров x86 :)

#include <iostream>
using namespace std;

int main() {
 unsigned int n = 1;
 char *c = (char*)&n;
 if (*c) cout << "little-endian";
 else cout << "big-endian";
 cin.get(); return 0;
}
Как узнать максимальное значение для беззнакового целого типа?

Можно так, если не хочется искать константу, содержащую это значение:

#include <iostream>
using namespace std;

int main() {
 unsigned int max = 0;
 max = ~max;
 cout << endl << "unsigned int: " << max;
 unsigned long long int max2 = 0;
 max2 = ~max2;
 cout << endl << "unsigned long long int: " << max2;
 cin.get();
 return 0;
}
Можно ли в C++ найти знак числа без использования любого (бинарного или тернарного) условного оператора?

Так как результаты выполнения операций отношения можно рассматривать как числовые значения, то вот так:

#include <iostream>
using namespace std;

int sign (int n) { 
 return (n>0) - (n<0); //Скобки нужны из-за приоритетов!
}

int main() {
 cout << endl << sign(3); //1
 cout << endl << sign(-1); //-1
 cout << endl << sign(0); //0
 cin.get(); return 0;
}

теги: c++ программирование список тест

06.03.2018, 17:06; рейтинг: 625

  свежие записипоиск по блогукомментариистатистикао "вирусах" в архивах .zip

Наверх Яндекс.Метрика
© PerS
вход