Розбираємося в складних оголошеннях Сі


Дізнайтесь більше про нові кар'єрні можливості в EchoUA. Цікаві проекти, ринкова оплата, гарний колектив. Надсилайте резюме та приєднуйтеся до нас.

Розповідає Брайан Барто


Вище Ви можете побачити список оголошень на мові Сі. Зовсім нещодавно я не міг сказати, що вони означають. Тепер же я можу цілком упевнено пояснити їх, вивчивши правила пріоритетів для оголошень у Сі.

У моєму випадку вивчення складних оголошень було важливим кроком до використання складних структур даних і розширення власних можливостей. Якщо я не можу прочитати складне оголошення, я не зможу його використати, а отже, мені доведеться використати гірші рішення.

Я думав, що для засвоєння цієї теми мені доведеться діяти за стандартною схемою “повторення – мати навчання”, але все виявилося на диво просто. Треба запам’ятати лише декілька правил – ось вони, в порядку зменшення пріоритету:

  1. Дужки, що об’єднують частини оголошення.
  2. Постфіксні оператори: круглі дужки (), що означають функцію, і квадратні [], що означають масив.
  3. Префіксний оператор: зірочка *, що означає покажчик.

Розпочнемо з четвертого оголошення з мого списку.

char* foo[5];

Правила пріоритетів говорять, що квадратні дужки старші за покажчик, тому foo – це масив покажчиків на символ, а не покажчик на масив символів.

Ось покроковий процес застосування правил до цього виразу. Розпочнемо з імені foo: “foo – це…”. Далі йдуть квадратні дужки: “foo – це масив з п’яти…”. Залишилася зірочка: “foo – це масив з п’яти покажчиків на…”. Додаємо тип і отримуємо: “foo – це масив з п’яти покажчиків на символ”.

Якби я хотів отримати покажчик на масив, то я повинен був би додати круглі дужки:

char (* foo)[5];// foo - це...// foo - це покажчик на...// foo - це покажчик на масив з п'яти...// foo - це покажчик на масив з п'яти символів

Цього разу круглі дужки підвищили пріоритет зірочки, і ми отримали покажчик на масив.

У восьмому оголошенні є дві пари круглих дужок:

char*  (*foo) (char*);// foo - це...// foo - це покажчик на...
// foo - це покажчик на функцію, що приймає покажчик на символ...// foo - це покажчик на функцію, що приймає покажчик на символ, повертає покажчик на...// foo - це покажчик на функцію, що приймає покажчик на символ, повертає покажчик на символ

Я трохи скоротив кількість кроків, але так, на мій погляд, навіть простіше. До параметрів функцій правила застосовуються аналогічно.

І останній приклад – найскладніше оголошення зі списку:

char*  (*(*foo[5])(char*))[];// foo - це...// foo - це масив з 5...// foo - це масив з 5 покажчиків на...// foo - це масив з 5 покажчиків на функцію, що приймає покажчик на символ...// foo - це масив з 5 покажчиків на функцію, що приймає покажчик на символ і повертає покажчик на...
// foo - це масив з 5 покажчиків на функцію, що приймає покажчик на символ і повертає покажчик на масив з...// foo - це масив з 5 покажчиків на функцію, що приймає покажчик на символ і повертає покажчик на масив з покажчиків на...// foo - це масив з 5 покажчиків на функцію, що приймає покажчик на символ і повертає покажчик на масив з покажчиків на символ

Зазначу, що останній приклад є крайнім випадком використання правил пріоритетів, і на практиці таке не вітається. Крім того, зверніть увагу, що в розглянутих прикладах не використовуються ключові слова на кшталт const і volatile, а також немає оголошень структур, перерахувань і об’єднань.

Переклад статті “Untangling Complex Declarations in C”

Київ, Харків, Одеса, Дніпро, Запоріжжя, Кривий Ріг, Вінниця, Херсон, Черкаси, Житомир, Хмельницький, Чернівці, Рівне, Івано-Франківськ, Кременчук, Тернопіль, Луцьк, Ужгород, Кам'янець-Подільський, Стрий - за статистикою саме з цих міст програмісти найбільше переїжджають працювати до Львова. А Ви розглядаєте relocate?


Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *