Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình C

Hàm inline trong C

Inline Function là gì?

Inline function: Gợi ý compiler thay thế lời gọi hàm bằng thân hàm (code substitution), tránh overhead gọi hàm (push/pop stack, jump).

Cú pháp


inline int binhPhuong(int x) {
    return x * x;
}

// Hoặc với static (file-scope)
static inline int binhPhuong(int x) {
    return x * x;
}

Chương trình ví dụ

#include <stdio.h>

inline int nhan(int a, int b) {
    return a * b;
}

int main() {
    int x = 5, y = 6;
    int kq = nhan(x, y);  // Có thể được thay bằng: x * y
    
    printf("%d * %d = %d\n", x, y, kq);
    return 0;
}

Kết quả


5 * 6 = 30

Khi nào compiler THỰC HIỆN inline?

Từ khóa inline chỉ là gợi ý (hint), compiler quyết định:

  • Inline: Hàm nhỏ, đơn giản, không đệ quy, không vòng lặp phức tạp
  • Không inline: Hàm lớn, đệ quy, có vòng lặp nhiều, lấy địa chỉ hàm (&func), virtual function (C++)

Inline vs Macro

Đặc điểm Inline Function Macro (#define)
Kiểm tra kiểuCó (type safety)Không (text substitution)
Đánh giá đối số1 lầnNhiều lần (bug tiềm ẩn)
DebugDễ (có symbol)Khó (không có symbol)
ScopeTuân theo quy tắc scopeGlobal từ điểm define
Overhead0 nếu inline thành công0 (luôn thay thế)

Ví dụ bug Macro vs Inline


// Macro nguy hiểm
#define BINH_PUONG(x) ((x) * (x))

// Inline an toàn
inline int binhPhuong(int x) {
    return x * x;
}

int main() {
    int i = 5;
    printf("Macro: %d\n", BINH_PUONG(i++));   // 5*6=30 (i++ đánh giá 2 lần!) -> i=7
    printf("Inline: %d\n", binhPhuong(i++));  // 7*7=49 (i++ đánh giá 1 lần) -> i=8
    return 0;
}

Static Inline (Header-only)

Để dùng inline trong header cho nhiều file .c:


// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

static inline int max(int a, int b) {
    return a > b ? a : b;
}

static inline int min(int a, int b) {
    return a < b ? a : b;
}

#endif
  • static inline: Mỗi file .c có bản copy riêng, không gây multiple definition
  • Phù hợp cho hàm nhỏ, dùng chung nhiều file
  • C99: inline không static → cần một file .c định nghĩa extern inline

Compiler Optimization

Compiler hiện đại (GCC, Clang, MSVC) tự động inline hàm nhỏ khi bật tối ưu hóa (-O2, -O3, -Os) ngay cả khi không có từ khóa inline.


// GCC
gcc -O2 -finline-functions main.c  // Tự động inline
gcc -O3 main.c                     // Tích cực hơn

Khi nào NÊN dùng inline?

  • Hàm nhỏ, gọi thường xuyên (getter/setter, toán tử đơn giản)
  • Hàm trong header (static inline)
  • Thay thế macro phức tạp
  • Performance-critical code (sau khi profile)

Khi nào KHÔNG nên dùng?

  • Hàm lớn (làm phình binary - code bloat)
  • Hàm đệ quy
  • Cần lấy địa chỉ hàm: func_ptr = &my_func;
  • Hàm có static variable bên trong (mỗi bản inline có bản copy riêng)

Tóm tắt

  • inline = gợi ý, không bắt buộc
  • Ưu tiên static inline trong header
  • An toàn hơn macro (type checking, evaluate once)
  • Compiler hiện đại tự inline tốt hơn tay
  • Dùng __attribute__((always_inline)) (GCC/Clang) nếu BUỘC phải inline