Як зробити очевидним, що функція доступна ззовні?


9

Це специфічне C питання. Я намагаюся зберегти все можливе в межах одиниці перекладу, відкриваючи лише кілька функцій через .hфайл. Тобто я надаю посилання на staticоб’єкти файлового рівня.

Тепер пару функцій потрібно викликати іншими модулями, але не безпосередньо. Мій модуль / файл / блок перекладу підписується на інші модулі, передаючи вказівник на функцію. Потім після конкретної події вказівник викликається деякими аргументами.

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

  • Повинні чи вони бути staticабо extern(і виставити їх в .h)?
  • Чи слід включати в назву функцій якусь підказку?
  • Або достатньо поставити коментар "зателефонував X"?

1
Це відмінне запитання. Моє рішення (з яким я зовсім не задоволений, тому я лише вкладаю це в коментар) - це зробити декілька файлів заголовків, чітко названих і групувати функції за обсягом, який я їм хочу мати. Для бібліотеки Астар я створив у мене AStar.h, AStar_private.h, AStar_packagePrivate.h тощо ...
Дракон

Відповіді:


2

З точки зору блоку (файлу) компіляції, єдине, про що ви повинні заклопотати себе, - це чи доступна функція зовні. Якщо зробити це доступним, це означає, що його потрібно було викликати, і ви повинні діяти за умови, що ці дзвінки відбудуться. Ваша турбота про саму функцію починається з початкової точки. Те, як контроль потрапляє туди, в першу чергу має значення лише для коду, який викликає це.

Оскільки зв'язок у кожній реалізації знань CI є символічним, все, що викликає функцію, повинно посилатися на її символ:

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

Якщо ви помилково оголосити foo(), що staticваша програма не пов'язувати. Якщо ви оголосите це не- static, у вас є відкрита функція, яка не викликається. Питання про те, чи використовується функція, можна вирішити, скидаючи таблиці символів ваших об’єктних файлів або шукаючи її в джерелах.


1

Тому я блукаю, як зробити так, щоб ці функції були очевидними з певного місця.

Визначте "незрозуміле".
Методи повинні бути відкриті через чітко визначені "інтерфейси", і, як уже запропонував Шиван Дракон, ці "інтерфейси" - це ваші файли .h. Якщо ви не надаєте іншій програмі "правильний" файл заголовка, він не може викликати метод.

Чи повинні вони бути статичними чи зовнішніми (і виставляти їх у .h)?

static може бути добре, доки у вас немає жодного класу [-подобні конструкції], що містить дані екземпляра.
externозначає, що ви насправді не реалізуєте це взагалі; реалізація "набувається" з інших місць в процесі зв'язування.

Чи слід включати в назву функцій якусь підказку?

Або достатньо поставити коментар "зателефонував X"?

Абсолютно ні.

Подібні коментарі, як би не були добромірні, застаріли в той момент, коли ви закінчите їх писати.


Адресуючи свою першу точку, функції викликаються наступним чином. Мій компонент включає зовнішній .hфайл. Він викликає функцію звідти і дає їй вказівник на одну з власних функцій модуля. Пізніше зовнішній код називає все, що є в цьому покажчику. Таким чином, мою функцію викликає хтось, хто не включає мій файл заголовка, а я включаю його.
Vorac

1
Щодо другого пункту, наскільки я розумію, об'єкт, визначений у області файлу, за замовчуванням має зовнішню зв'язок; тому externключове слово зайве " .
Vorac

0

Якщо функції зворотного дзвінка визначені у вашому модулі, і користувач ніколи не надасть жодного свого, я думаю, ви можете використовувати заповнювач місця на етапі ініціалізації. Заставником заповнення, як правило, enumє внутрішнє переведення у потрібну staticфункцію.


0

Я б все-таки зробив їх static(вони не призначені для того, щоб їх пов'язував і не називав хтось), і позначив їх призначення як зворотні дзвінки, надані зовнішнім функціям від їх імені.

static тому що я намагаюся приховати те, що можу приховати, стільки, скільки можу приховати.

Позначте їх своїм іменем, оскільки а) коментарі застаріли, і б) в місці надання зворотного дзвінка стає очевидним, що ця функція призначена для використання таким чином: це в основному робить її червоним прапором приймати адресу функції, яка не відповідає умові іменування.


0

Модифікатори сфери застосування повинні використовуватися насамперед як інформація для компілятора, а не як форма "достатньо близької" документації. Використання, staticзокрема, дозволяє компілятору C зробити функцію непридатною для використання поза модулем, в тому числі як зворотний виклик - не те, що потрібно, хоча це може працювати з вашим поточним компілятором.

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

Отже, єдиний варіант, який залишився - це назвати функцію, щоб вказати, що це зворотний дзвінок. Більшість прикладів я бачив у використанні _callbackабо _cbяк суфікс, або cb_як префікс. Використовуйте довгу форму, якщо зворотні виклики у вашому коді незвичні, коротку форму, якщо вони є загальними.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.