Вопросы с собеседований:

Массивы и арифметика указателей:


  1. Что выведет в консоль следующая программа:
    #include <iostream> int main(){ int a[]= {1,1,1,1, 1,1,1,1, 1,1,1,1}; *((long long *)a + 2) = 0; for(int i = 0; i < 12; i++){ std::cout << (int)a[i] << " "; } }

  2. Чему будет равно a3?
    int main(){ int a2[] = {1, 2, 3, 4, 5, 6}; int a3 = (1 + 3)[a2] - a2[0] + (a2 + 1)[2]; }

  3. Что выведется на экран консоли и почему?
    #include <iostream> int main(){ char str[5] = "emacs"; std::cout << str << "\n"; }

  4. Что выведет программа?
    #include <iostream> int main(){ int str[5] = {1,2,3}; std::cout << str[-2] << "\n"; std::cout << str[3] << "\n"; }

  5. Чему будет равно a2?
    int main(){ int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int a2 = a[&a[3] - &a[1] + &a[9] - &a[5]]; }

  6. Что будет напечатано после выполнения следующей программы:
    #include <iostream> int main(){ int *ptr = (int*)1024; ptr = ptr + 2; std::cout << (long)ptr << std::endl; }

  7. Чему равно p?
    int main(){ int *ptr1 = (int*)1000; int *ptr2 = (int*)2000; int p = ptr2 - ptr1; }

  8. Вопросы для развлечения


  9. Будет ли компилироваться следующий код?
    int main(){ int a<::> = <%1, 2, 3, 4, 5, 6%>; }

  10. Что выведет программа?
    #include <iostream> int main(){ char str[] = "const int"; char *p = str; std::cout << (p + p[4] - p[2]) << std::endl; }

Ответы:

  1. Ответ: 1 1 1 1 0 0 1 1 1 1 1 1.
    Объяснение: при приведении к указателю на long long, увеличенный указатель будет указывать не на a[2], а на a[2*sizeof(long long)/sizeof(int)] = a[2*8/4] = a[4]. А обнулено будет не одно значение, а два, потому что sizeof(long long)/sizeof(int) = 2.

  2. Ответ: 8
    Объяснение: в этом вопросе необходимо понимать, что a[i] сразу преобразуется компилятором в *(a + i), а от перемены слагаемых сумма не меняется. Значит можно поменять их местами и 1[a] тоже, что и a[1].
    (1 + 3)[a2] = a2[4] = 5
    (a2 + 1)[2] = a2[3] = 4
    5 - 1 + 4 = 8

  3. Ответ: ничего, программа не откомпилируется.
    Объяснение: потому что места для строки не хватит. В конец строки компилятором всегда кладется дополнительный символ \0. Массив должен быть объявлен для 6 элементов, тогда в консоль будет выведена строка "emacs".

  4. Ответ: по индексу -2 выведется мусор, а по индексу 3 выведется 0.
    Объяснение: отрицательные индексы допустимы и отлично компилируются, и задача программиста -- следить за тем, чтобы индекс не выходил за границы массива. Если элементы массива не проинициализированы, им будет присвоен 0.

  5. Ответ: 7
    Объяснение:
    &a[i] -- это адрес элемента i, результатом вычитания адресов
          будет количество элементов между эти адресами.
          
    &a[3] - &a[1] = 3 - 1 = 2
    &a[9] - &a[5] = 9 - 5 = 4
    a[2 + 4] = a[6] = 7

  6. Ответ: 1032
    Объяснение: вопрос из арифметики указателей. При прибавлении числа к указателю прибавляется не это число, а число умноженное на размер типа указателя.
    Значит, 1024 + 2*sizeof(int) = 1024 + 8 = 1032

  7. Ответ: 250
    Объяснение:
    (2000 - 1000)/sizeof(int) = 1000/4 = 250

  8. Ответ: да.
    Объяснение: по стандарту (стр.20, в pdf стр. 35) символ [ имеет альтернативу <:, а у { альтернативный символ <%.

  9. Ответ: int
    Объяснение: для ответа на этот вопрос необходимо знать таблицу символов ASCII.
    p[4] = 't' = 116
    p[2] = 'n' = 110
    p + (116 - 110) = p + 6
    Значит, напечатается строка, начиная не с 0-го символа, а с 6-го. А именно, 'int'. В книге Б. Кернигана и Д. Ритчи "Язык программирования Си", на стр. 39 встречается использование этого свойства кодирования символов.