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

Truyền tham trị (Call by Value) trong C

Khái niệm

Truyền tham trị (Call by Value / Pass by Value): Hàm nhận bản sao (copy) của giá trị đối số. Thay đổi tham số trong hàm KHÔNG ảnh hưởng đến biến gốc.

Minh họa: Hoán đổi 2 số (KHÔNG thành công)

#include <stdio.h>

void hoanDoi(int a, int b) {
    int tam = a;
    a = b;
    b = tam;
    printf("Trong ham: a=%d, b=%d\n", a, b);
}

int main() {
    int x = 10, y = 20;
    
    printf("Truoc goi ham: x=%d, y=%d\n", x, y);
    hoanDoi(x, y);  // Truyền giá trị
    printf("Sau goi ham: x=%d, y=%d\n", x, y);
    
    return 0;
}

Kết quả

Truoc goi ham: x=10, y=20
Trong ham: a=20, b=10
Sau goi ham: x=10, y=20  // KHÔNG thay đổi!

Sơ đồ bộ nhớ

main():           hoanDoi():
┌─────────┐       ┌─────────┐
│ x = 10  │       │ a = 10  │  ← Bản sao của x
├─────────┤       ├─────────┤
│ y = 20  │       │ b = 20  │  ← Bản sao của y
└─────────┘       └─────────┘
  Địa chỉ khác nhau hoàn toàn

Đặc điểm Call by Value

Đặc điểm Mô tả
An toàn dữ liệuBiến gốc không bị thay đổi
Bộ nhớCấp phát bản sao (tốn thêm stack)
Hiệu năngChậm với struct/mảng lớn (copy tốn thời gian)
Mặc định CMọi kiểu dữ liệu cơ bản đều pass by value
MảngTruyền địa chỉ phần tử đầu (pass by reference thực chất)

Khi nào dùng Call by Value?

  • Dữ liệu nhỏ (int, float, char, struct nhỏ)
  • Không muốn hàm thay đổi biến gốc (bảo vệ dữ liệu)
  • Hàm chỉ đọc, không ghi (read-only)

Ví dụ thực tế: Tính toán không làm thay đổi đầu vào

#include <stdio.h>
#include <math.h>

// Tính chu vi, diện tích hình tròn - KHÔNG thay đổi r
void tinhHinhTron(float r, float *chuVi, float *dienTich) {
    *chuVi = 2 * M_PI * r;
    *dienTich = M_PI * r * r;
    // r không bị thay đổi
}

int main() {
    float r = 5.0, cv, dt;
    tinhHinhTron(r, &cv, &dt);  // r truyền by value, cv/dt truyền by reference
    printf("Ban kinh: %.2f\n", r);
    printf("Chu vi: %.2f\n", cv);
    printf("Dien tich: %.2f\n", dt);
    return 0;
}

So sánh: Call by Value vs Call by Reference

Tiêu chí Call by Value Call by Reference (qua con trỏ)
Cú pháp gọifunc(x)func(&x)
Tham số hàmvoid func(int x)void func(int *x)
Truy cập trong hàmx*x
Ảnh hưởng biến gốcKhôngCó
Dùng choĐọc, tính toán nhỏGhi, struct lớn, mảng, trả nhiều giá trị

Mẹo: Trả về nhiều giá trị với Call by Value

C chỉ return 1 giá trị. Dùng struct để gom nhiều giá trị:

struct KetQua {
    int tong;
    int hieu;
    int tich;
    float thuong;
};

struct KetQua tinhToan(int a, int b) {
    struct KetQua kq;
    kq.tong = a + b;
    kq.hieu = a - b;
    kq.tich = a * b;
    kq.thuong = (float)a / b;
    return kq;  // Trả về struct (copy)
}

Hiểu rõ Call by Value giúp tránh bug "hàm không thay đổi được biến" - một lỗi cực phổ biến của người mới học C.