
Дізнайтесь більше про нові кар'єрні можливості в EchoUA. Цікаві проекти, ринкова оплата, гарний колектив. Надсилайте резюме та приєднуйтеся до нас.
Розповідає Брайан Барто
Вище Ви можете побачити список оголошень на мові Сі. Зовсім нещодавно я не міг сказати, що вони означають. Тепер же я можу цілком упевнено пояснити їх, вивчивши правила пріоритетів для оголошень у Сі.
У моєму випадку вивчення складних оголошень було важливим кроком до використання складних структур даних і розширення власних можливостей. Якщо я не можу прочитати складне оголошення, я не зможу його використати, а отже, мені доведеться використати гірші рішення.
Я думав, що для засвоєння цієї теми мені доведеться діяти за стандартною схемою “повторення – мати навчання”, але все виявилося на диво просто. Треба запам’ятати лише декілька правил – ось вони, в порядку зменшення пріоритету:
- Дужки, що об’єднують частини оголошення.
- Постфіксні оператори: круглі дужки
()
, що означають функцію, і квадратні[]
, що означають масив. - Префіксний оператор: зірочка
*
, що означає покажчик.
Розпочнемо з четвертого оголошення з мого списку.
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?