Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
otvety_na_voprosy_po_proge.doc
Скачиваний:
3
Добавлен:
01.03.2025
Размер:
246.27 Кб
Скачать

33. Определите назначение операций ? , (тип)

? - краткая условия: (условие) ? (выражение, которое вернёт, если верно) : (выражение, которое вернёт, если ложь). Можно записать модуль b = abs(a)  b = (a < 0) ? –a : a

, - задание последовательности. Это бинарный оператор, то есть, ему нужны два операнда. Обрабатываются операнды слева направо. Результат работы - второй операнд. Например, если вы напишете i = (1,2); то в переменной i окажется значение 2. Разумеется, можно поставить в выражение и несколько таких операторов. Так, строка i = ( 1, 3, -4 ); зашлет в i значение -4. Обратите внимание на круглые скобки - они, как обычно, помогают бороться с приоритетами операций, и в данном случае они совершенно необходимы. Если вы попытаетесь написать, например, так: i = 1, 3, -4 ; то с удивлением обнаружите, что переменная i стала равна единице, а не -4. А все дело в том, что у оператора присваивания приоритет повыше, так что написать последнюю строку все равно, что написать result = ( (i=1), 3, -4 ); а потом забыть про result и использовать значение i. Зачем понадобился такой необычный оператор? Прежде всего, есть в программах на С такие места, куда можно поставить только одно выражение, а надо ставить несколько. Вот в таких случаях и пишут что-нибудь в таком духе: f(( (i=1), (j=2), i*j ) )); То, что вы видите - вызов функции с одним аргументом. В конечном итоге, в качестве аргумента функция получит i*j. И правила языка не нарушены, и несколько выражений стоит. Эта же строка показывает и второе полезное применение этого оператора - мы прямо в вызове функции присвоили новые значения переменным i и j, и только после этого сосчитали значение аргумента i*j; То есть, с помощью оператора запятая можно гарантировать, что обработаются все операнды, причем обработаются они последовательно - слева направо. Еще один пример, чтобы вам этот оператор получше запомнился. В строке программы f(), g(), h(); последовательно будут вызваны все три функции f(), g(), h();

(тип) - это оператор приведение, позволяющий переменную 1 типа привести к другому типу например double d = 2.0; int i = (int)d;

34. Укажите особенности выполнения операций % <<

% - работает стандартно только для целых, и в математике остаток от деления ­-3 на 2 будет 1, а (-3) % 2 будет равно -1

<< – выполняется намного быстрее, чем операция умножения. При этом операнды должны быть целыми.

35. Можно ли сравнивать указатели?

int x=100;

double y;

int* p=&x;

if (p!=NULL) x=y;

36. Приведите примеры использования операции преобразования типа.

double d = 2.0;

int k = (int)d;

char ch = (char)k;

int x= static_cast<double> d*10;

37. Определите понятие «пустой оператор».

оператор, в котором ничего не выполняется, может использоваться в циклах

int i;

for (i = 0; ar[i] != 0; i++) ;

находит первый нулевой элемент в массиве, при этом в теле цикла ничего не выполняется

38. Каждый ли оператор заканчивается «точкой с запятой»?

Нет, например:

{ [oбъявление] : оператор; [оператор]; : } – составной оператор

39. Опишите синтаксис оператора if. Как интерпретировать вложенные if?

if (условие) { оператор 1; оператор 2; оператор 3;}// если оператор один фигурные скобки не ставятся

if(a == b)

if(b == c)

cout << ”a, b и c равны \n”;

else

cout << “b и c не равны \n”;

40. Как интерпретировать следующее выражение if (a=b) выражение; ?

Cначала переменной a присваивается значение b, а потом если а не NULL или не 0, то выполняется «выражение».

41. Как интерпретировать следующее выражение if (a<x<b) выражение; ?

Вначале выполниться проверка первого условия, а потом bool результат приведётся к int (0 или  1) и произойдет проверка второго условия. Т.е. например if (-5<-3<-1) будет всегда интерпретировано как false.

42. Как интерпретировать следующее выражение if (int i=fun(t)) выражение; ?

i=fun(t).  Если fun(t)!=0, то выражение будет интерпретированно как true, иначе false;

43. Опишите синтаксис оператора switch. Как организовать выход из оператора switch?

switch – оператор множественного выбора

switch (переменная) { case значение 1: оператор1; break;

case значение 2: оператор2; break;

case значение 3: оператор3; break;

default: оператор;

}

44. Опишите синтаксис оператора цикла с предусловием. Как организовать в этом случае бесконечный цикл?

while (условие выполнения) {список операторов}. Бесконечный цикл – while (true).

45. Опишите синтаксис оператора цикла с постусловием. Как организовать в этом случае бесконечный цикл?

do {список операторов} while (условие выполнения). Бесконечный цикл –do{} while (true).

46. Опишите синтаксис оператора цикла for. Как организовать бесконечный цикл с использованием оператора for? Как описывается список инициализаций?

for (инициализация переменной счетчика; условие; изменение переменной счетчика) {

оператор 1; оператор 2; }

бесконечный цикл – for (int i=1; i>0; i++)

47. Опишите использование оператора break.

break – выход из ближайшего цикла. Следующим оператором, исполняемым после break, будет являться первый оператор, находящийся вне данного цикла.

48. Опишите использование оператора continue.

continue– переход к следующему шагу ближайшего цикла.(используется внутри цикла, бросит вычисления одной ветки и перейдёт к другой)

49. Опишите использование оператора return.

Оператор return завершает выполнение функции, в которой он задан, и возвращает управление в вызывающую функцию, в точку, непосредственно следующую за вызовом.

return [выражение] – выход из функции или процедуры (без выражния).

50. Определите понятие «указатель». Как определить указатель на функцию? Можно ли определить указатель на указатель? Если да, то дайте объяснение, что это за объект.

Указатель – это целочисленная переменная, содержащая адрес (номер ячейки памяти) другой переменной.

Указатель на функцию:

возвращаемый  тип(*имя указателя)(аргументы) пример: int (*sum)(int,int)

Например: void(*pf)(string); void f1(string) {...} pf = &f1; (*pf)(“qwe”); //вызов функции f1 через указатель pf

Можно определить указатель на указатель. Например: int **ptr; Это указатель на область памяти, в которой храниться указатель на необходимый объект.

51. Определите указатель на константу. Определите константный указатель. Определите константный указатель на константу.

const int*ptr // указатель на константу

int* const ptr // константный указатель

const int* const ptr // константный указатель на константу

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

int *a = &b; // где b –имеет тип int;// с использованием операции &

указатель на void – это указатель на любой тип данных (пример void* ptr)

void(*pf)(string) = f1; // где void f1(string);

int *c = d; // где d – имеет тип int*;// используя другой указатель

int *p = A; // где int A[size];// используя имя массива

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

54. Укажите способы инициализации указателей, используя операции new и new[].

int *p;

p = new int;

int *a;

a = new int [size];

55. Опишите использование операций delete и delete[].

Операции delete и delete[] предназначены для очистки неиспользуемой памяти при ручной работе с динамической памятью. Т.е. для удаления элементов созданных при помощи команд new и new[] соответсвенно.

delete имя указателя;// удалить область памяти по адресу

delete []имя указателя;// удалить массив по адресу

56. Проинтерпретируйте выражение int *(*p[10])()

Массив из 10 указателей на функции которые ничего не принимают и возвращают указатель на int.

57. Проинтерпретируйте выражение int *(*p[10])(int *)

Массив из 10 указателей на функции которые принимают указатель на тип int и возвращают указатель на тип int.

58. Укажите особенности выполнения операций ++ --

Оператор ++ увеличивает на 1 значение переменной, которая стоит справа (слева) от него. (Стоит заметить, что при использовании с указателями данный оператор увеличивает значение указателя не на единицу, а на n, где n – размер в байтах того типа данных, на который указывает указатель).

Данный оператор имеет две формы: префиксную и постфиксную. Различие в том, что происходит раньше: использование значения переменной в выражении или же инкремент переменной. Наприме: 1) int x, y = 10; x = ++y; // префиксная форма – сначала происходит инкремент переменной y, а затем полученное значение присваивается переменной x cout << x << " " << y; В итоге в консоль будет выведено: 11 11 2) int x, y = 10; x = y++; // постфиксная форма – сначала значение y, равное 10, присваивается переменной х, а затем происходит инкремент переменной у. cout << x << " " << y; В итоге в консоль будет выведено: 10 11 Обе формы возвращают значение того же типа данных, что и операнд. Но важное различие заключается в том, что значение, возвращаемое префиксной формой, является l-value, в то время как значение, возвращаемое постфиксной формой оператора ++, не является l-value. Справка: l-value - это то, чему можно присваивать значение, т.е. выражение, которое может быть расположено слева от оператора присваивания (=). На самом деле это не совсем так, но для понимания проще всего. Формально, l-value - выражение типа, отличного от void, ссылающееся на область памяти. При этом l-value может быть и не модифицируемым. Например, переменная, объявленная как const является l-value, однако ее значение нельзя изменять: const int i = 0; i = 1; // error C3892: 'i' : you cannot assign to a variable that is const l-value может быть: - идентификатор переменной любого из следующих типов: - целочисленного - с плавающей точкой - указатель - структура (struct) - или союз (union) - выражение с индексом ([ ]) не являющееся само массивом - обращение к члену (–> или .) - выражение взятия значения (*) не являющееся массивом - любое l-value в скобках - любое l-value со спецификатором const (немодифицируемое l-value) То есть можно считать, что префиксная форма возвращает ссылку на операнд (имеющий уже измененное значение), а постфиксная форма возвращает просто значение операнда (причем не измененное значение, так как инкремент будет произведен позже). То же самое касается и оператора – с той лишь разницей, что он осуществляет не инкремент, а обратную операцию - декремент (т.е. уменьшение на единицу).

59. Укажите особенности выполнения операций + - для указателей. Укажите особенности выполне-ния операций ++ -- для указателей.

Операции + и -:

К указателю можно прибавить целое число, причем выражение p = p + i; где p – указатель на переменную типа Type, а i – переменная типа int, не означает, что значение указателя увеличится на i. В такой ситуации значение указатля увеличится на i*sizeof(Type), т.е. произойдет сдвиг указателя на i блоков памяти, какждый из которых по количеству занимаемой памяти равен переменной типа Type. Аналогично для -.

Перегружена также разность для указателей, которая вернёт кол-во объектов типа, на который указывают указатели, находящихся между ними. Пусть p1 , p2 - указатели на type и имеют адреса c1 и с2 (в интах) Тогда значение выражения (p2 - p1) равно (c2 - c1) / sizeof(type).

Сложение двух указателей невозможно!!!

Операции ++ и -- :

Изменение указателя зависит от размера типа на который он указывает. ++i/--i – l-value, i++/i-- - не l-value.

60. Укажите особенности присвоения для указателей типа void.

Указатель любого тип можно присвоить переменной типа void*, void* можно присвоить void*, пару void* можно сравнивать на равенство/неравенство, явно приводить к любому типу.

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

61. Дайте интерпретацию следующим выражениям

p++=10 (p)++=10, где р – указатель

Ошибка копмпляции.

Во первых - p++ - не l-value. Во-вторых, мы не можем присвоить указателю целочисленное значение без при-ведения типа.

62. Определите понятие «ссылка». Как инициализировать ссылку?

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

int a = 1;

int& b = a;

63. Как изменить значение ссылки после инициализации? Можно ли построить ссылку на ссылку? указатель на ссылку?

Изменить значение ссылки после инициализации нельзя, т.к. ни один оператор не выполняет действий над ссылкой.

Нет нельзя построить ссылку на ссылку, оператор не выполняет действий над ссылкой.

int& b = a;

int *ptr = & b; // ptr указывает на a;

64. Определите понятие «массив». Приведите примеры инициализации массива. В каких случаях можно опустить указание размерности массива?

Массив – это последовательная группа переменных, имеющих одно имя и один тип.

int A[]={1,2,3,4,5};

Указание размерности массива можно опустить, если при инициализации указанны все его элементы.

65. Как создать динамический массив из n элементов?

int *A;

int n;

A = new int[n]; // можно сразу: int *A=new int[n]

66. Как описываются многомерные массивы? организуется доступ к его элементам? Приведите примеры инициализации многомерных массивов.

int A[5][8]; //массив из 5 массивов по 8 целых;

A[i][j] – доступ к (i,j) элементу

int A[2][5]={{1,2,3,4,5},{6,7,8,9,10}};

int M[2][5]={{1,2,3,4,5},{1}}; //недостающие элементы буду дополнены 0;

67. Приведите пример создания 2-мерного динамического массива.

int **p;

int n=10, m=5;

p = new int*[n];

for(int i=0;i<n;i++)

p[i] = new int[m];

68. Укажите отличия

char str[]=”qwerty”; char str[10]=”qwerty”; char *str=”qwerty”;

в первом случае памяти будет выделено ровно на 7 элементов – на само слово и на ноль в конце

в втором памяти будет на 10 элементов.

В третьем, случае str - указатель на char. Проблема в том, сам по себе указатель можно изменять, но указателю присваивается адрес строкового литерала, который является константным. Таким образом, мы можем считать строку, на которую указывает str, но изменить её, т.е. написать нечто вроде str[3] = '2'; мы не можем.

Стоит ещё добавить, что *str – указатель на константу, так что отдельные символы изменять нельзя, в отличие от str[] и str[10]

69. Как присвоить один массив другому?

1) void *memcpy(void *dest, const void *src, size_t count)

Пример: int s[10], d[7]; memcpy(s, d, sizeof d);

2) for (int i=0; i<10; i++) s[i] = d[i];

70. Как присвоить одну строку другой?

  1. Так же, как и массив

  2. #include <string> / #include <string.h>

strcpy(s, d);

71. Приведите пример использования typedef для определения новых типов.

typedef char STRING – это объявление означает, что в объявлениях можно заменить тип char на STRING

72. Приведите пример использования перечисления enum c инициализацией и использованием.

В С++ предусмотрен способ объявления набора целых переменных в виде определенного пользователем перечислимого типа, который вводится ключевым словом enum. Перечисление используются в тех случаях, когда переменные создаваемого типа могут принимать заранее известное конечное (и, как правило, небольшое) множество значений. ПРИМЕР:

#include <iostream>

using namespace std;

enum days_of_week { Sun, Mon, Tue, Wed, Thu, Fri, Sat }; // объявление перечисляемого типа

int main()

{

days_of_week day1, day2; //определение переменных, хранящих дни недели

day1 = Mon; // инициализация переменных

day2 = Thu;

int dif = day2 – day1;// арифметическая операция

cout<< “Разница в днях: “<< dif << endl;

if (day1 < day2) //сравнение

cout<< “day1 наступит раньше, чем day2\n”;

return 0;

}

Объявление типа начинается со слова enum и содержит перечисление всех возможных значений переменных создаваемого типа. Эти значения называются константами перечисляемого типа. Перечисляемый тип days_of_week включает в себя 7 констант перечисляемого типа: Sun, Mon, Tue, и т.д до Sat.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]