Skip to main content

Tham chiếu, tham trị và hàm

Note: các thuật ngữ nào đc chú thích bằng tiếng Anh bên cạnh thì sau đó sẽ đc thay thế bằng tiếng Anh, lý do thói quen!)

Tham chiếu ( Pass by Reference ) & Tham trị (pass by value) là 2 thuật ngữ dùng trong lập trình (đặc biệt là C)
Tham chiếu là gán cho hàm tham số (argument) là 1 địa chỉ.
Tham trị là gán cho hàm tham số là 1 giá trị.



VD:
Ví dụ điển hình rất nổi tiếng là hàm swap (đổi giá trị của 2 số)

Nếu pass by value:

#include

void swap(int a, int b)
{
int c;
c = a;
a = b;
b = c;
return;
}

int main()
{
int x = 5, y = 7;
swap(x,y);
printf("x: %d, y : %d\n",x,y);
return 1;
}

kết quả sẽ là : x: 5, y: 7

Vậy hàm của mình đã viết là không có tác dụng! Vì sao?

Lý do bởi khi x và y được gán làm tham số của swap ( pass by value), hàm swap sẽ copy 2 giá trị của x và y rồi thực hiện các dòng lệnh với 2 "biến" copy đó. Để dễ hiểu, tưởng tượng là hàm swap tạo ra biến x1 chứa giá trị của x, biến y1 chứa giá trị của y. Sau đó tạo biến c copy giá trị của x1, gán y1 cho x1, gán c cho y1. Kết thúc hàm, biến c, x1,y1(tưởng tượng) sẽ bị hủy lập tức. Bởi thế không có gì tác động làm thay đổi gía trị của x và y cả.

Vậy làm thế nào để đảo giá trị của chúng? Câu trả lời là Pass by reference(tham chiếu).
Tác dụng của pass by reference là gì?
- Mang kết quả ra khỏi hàm.
Bình thường, 1 hàm trong C có thể trả về tối đa 1 giá trị hoặc không giá trị nào (hàm kiểu void). Bằng cách pass by reference, ta sẽ có thể nhận được bao nhiêu giá trị trả về tùy ý.

Trong ví dụ swap này, ta cần trả về 2 giá trị của x và y. Có nhiều cách để thực hiện điều này (không chỉ mỗi pass by reference), nhưng ở đây ta sẽ dùng PBR.

Thay vì tham số cho hàm swap là 2 giá trị của x, và y. Ta gán cho nó địa chỉ của 2 biến đầu vào. Ta viết lại hàm swap, lấy tên là swapRef.

#include
void swapRef(int *a, int * b)
{
int c;
c = *a;
*a = *b;
*b = c;
return;
}

int main() {
int x = 5, y = 7;
swapRef(&x,&y);
printf("SwapRef: x: %d, y: %d\n",x,y);
return 1;
}

kết quả trả về là x = 7, y = 5 .

Giải thich thêm một chút, &x là địa chỉ của biến x, &y là địa chỉ của biến y.
*a là giá trị mà địa chỉ con trỏ a trỏ đến. khi chương trình chạy, a là &x, *a = *&x = x.


Vậy mỗi khi thay đổi giá trị của 1 biến, ta đưa con trỏ tới biến đó vào đầu vào của hàm, và nhận về giá trị đã thay đổi khi hàm chạy xong.

PS: các bạn test và comment xem có lỗi gì không.

Written by FamiHug on 01/06/2011

Comments

  1. " Vậy làm thế nào để đảo giá trị của chúng? Câu trả lời là Pass by reference(tham trị).
    Tác dụng của pass by reference là gì?"

    tham tri => tham chieu.
    hinh nhu hoi nham cho nay .

    ReplyDelete
  2. ok, đã sửa, thế là cũng có đứa đọc bài mình viết :))

    ReplyDelete
  3. Các tham số của hàm được tạo ra khi gọi hàm và nhận vào các giá trị từ bên ngoài, nó sẽ mất đi khi kết thúc hàm. Việc truyền một địa chỉ vào hàm mục đích là thao tác trực tiếp với ô nhớ có địa chỉ chứa trong con trỏ.
    VD *a là một tham số thì lệnh a = xxx sẽ không có tác dụng khi ra khỏi hàm.
    Thêm nữa khi khai báo tham số cho hàm là : const data_type *a sẽ không cho phép thay đổi nội dung ô nhớ mà a trỏ đến (bảo vệ dữ liệu) và khai báo data_type const *a sẽ không cho phép thay đổi nội dung của con trỏ a (bảo vệ con trỏ tránh những tác động không mong muốn).

    ReplyDelete
  4. ứng dụng của PBR đó là khi viết chương trình lớn (project) với nhiều chức năng , mà số biến lại không đổi với mỗi lần thực hiện chức năng , thì khi đó PBR tỏ ra rất hiệu quả
    VD :
    nhập vào các hệ số để biện luận nghiệm của phương trình bậc 2
    nhưng cùng lúc đó , muốn nhập vào 1 hệ số khác để có 1 kết quả khác mà không phải cấp thêm biến số thì phải dùng PBR tác động vào giá trị của biến trước đó .

    ReplyDelete
  5. Pass by Reference là khái niệm của C++
    C ko có PBR. Như cái ở trên hình như là Pass by Pointer.
    Hồi trước đọc trên congdongcviet nhớ có ông bảo thế

    ReplyDelete
  6. vừa đọc lại C programming language của Ritchie, đúng là ko có PBR,
    Trong sách có đoạn:
    "The way to obtain the desired effect is for the calling program to pass pointers to the values to be changed"
    Thế nên gọi là PBP chắc là hợp lí :D

    ReplyDelete
  7. trc đây cũng từng nghe nói "bảo vệ con trỏ" nay mới nhìn thấy là ko có gì đặc biệt ngoài việt dùng type-qualifier "const" . (A const object may be initialized, but not thereafter assigned to. The purpose of const is to announce objects that may be placed in read-only memory, and perhaps to increase opportunites for optimization).
    Đi một ngày đàng, học một nhà hàng khôn :))

    ReplyDelete
  8. hôm nay cái này mới phát huy tác dụng

    ReplyDelete

Post a Comment

Popular posts from this blog

Tài liệu và hướng dẫn học Python

Để tiết kiệm thời gian, tốt nhất là đi học PyMI Updated: 130617 Sau đây là các tài liệu khuyên dùng: Vì nhiều lý do, nên học python2.7 tại thời điểm hiện tại (giờ là tháng 6/2013 - muốn biết tại sao thì tự tìm hiểu) python 3.5+ (giờ là tháng 2/2017) Chuẩn bị: 1. biết bật tắt máy 2. biết cài python 3. tập gõ 10 ngón - gõ 2 ngón hay 1 ngón cũng không sao, nhưng 10 ngón là cách dễ nhất để gõ nhanh nhất. Tài liệu - Nên dùng tài liệu tại trang chủ của Python làm chính, tham khảo thêm các tài liệu khác tại http://www.familug.org/2016/12/free-ebook.html Căn bản, mới học 1.1 Python PyMI.vn https://pymi.vn/tutorial/ 1.2. Python offical tutorial kết hợp làm bài tập trên HackerRank  (đề bài bằng tiếng Anh, nhưng Google translate 1 lúc cũng ra vì có nhiều ví dụ mẫu đi kèm). Học viên của Pymi.vn có rất nhiều học viên đã tự học với Learn Python the hard way nhưng chưa thấy ai thành công cả. Hai link dưới nên đọc sau khi đã nắm được những phần cơ bản của ngôn ngữ pytho...

The PyMiers

New FAMILUG