Що таке інтрінсікі (intrinsics) stack overflow російською

Ось конкретний приклад з VC ++.

Компілюємо з відключеною оптимізацією (/ Od). При наявності #pragma intrinsic (strlen) отримуємо

А при відсутності -

(Для інформації - при включеній оптимізації однаково в обох випадках -

Тобто в певному сенсі це inline-функції, тільки з заздалегідь готовим асемблерним кодом.

В С / С ++ будь-яка сутність, оголошена, але не певна в межах компилируемого файлу вважається зовнішньої. Це також стосується функцій в не меншому ступені, до ніж до змінних. Посилання на зовнішні функції залишаються в скомпільованому об'єктному файлі і будуть замінені на звернення до справжніх сутностей тільки на етапі компонування, якщо все міжмодульні залежності будуть задоволені. Не існує ніякої різниці між PrivetVasya () і printf () - з точки зору компілятора обидві абсолютно рівнозначні і про обидві можна сказати «так це просто якісь зовнішні функції». Коли ідіотські підручники або вчителя-недоучки починають говорити «вбудована функція мови printf ()» (а це дуже популярний марення) - треба розуміти, що це просто дурість, що в мову нічого такого не вбудовано, що компілятор обробляє виклик до printf () на тих же умовах, що і виклик до будь-якої іншої функції, та хоч в сусідньому файлі реалізованої. Що стосується тієї ж printf () - то це не вбудована функція мови, а функція стандартної бібліотеки мови. Стандарт на мову цю функцію описує, проголошує її наявність в стандартній бібліотеці, але сам компілятор до стандартної бібліотеці відношення не має - вона може з'явитися на етапі компонування, а може і взагалі не з'являтися.

Тим не менш, є воістину вбудовані функції. для яких в компіляторі насправді реалізована особлива обробка - вони називаються intrinsic-ами. У різних компіляторів набір intrinsic десятків різний. Intrinsic-му може бути і функція, яка штатно повинна жити в стандартній бібліотеці. При виклику intrinsic-функції компілятор генерує особливий код, характерний саме для даної функції: не генерується ніякого call-а, не буде ніякого реального виклику і повернення, а буде кілька інструкцій, що виконують потрібну задачу. Наприклад дуже поширений intrinsic memcpy () компілюється не в виклик якоїсь функції, а в інструкцію repnz movs (приклад для x86).

Ясна річ, що в стандартній бібліотеці С (libc) для AVR є деякі функції, які забезпечують затримку. Природно, це повноцінні функції, які всередині крутять цикл. Якщо потрібна затримка у 1-2 такту, то природно, такі великовагові функції не підходять. Зробити затримку в 1 такт повноцінної (і звичайної) функцією не можна: навіть якщо це буде абсолютно порожня функція, інструкція call виконується за 4 такту, і інструкція ret - ще 4 такту, разом 8 тактів на виклик порожньої функції.

Без найменшої зайвої думки зрозуміло, що затримки в одиниці тактів (менше 8) можуть бути реалізовані тільки intrinsic-ами. І тепер, схрестивши пальці, запитаємо: а чи є в avr-gcc delay-функції (функції затримки), виконані як intrinsic-і? Дійсно є такий intrinsic - функція називається __builtin_avr_delay_cycles ().