Tuesday, March 15, 2016

Khai Báo *& Trong C++ Có Ý Nghĩa Gì? - CONTINUE

Sai lầm trong suy nghĩ

Có nhiều thật nhiều người nói rằng trong C, ta có thể sử dụng con trỏ trong tham số của hàm như là 1 tham biến, qua hàm ta có thể thay đổi được giá trị của tham số.
tôi xin khẳng định lại, điều này thật là 1 hiểu lầm, sai lầm trong suy nghĩ, 1 sự hiểu biết nông cạn, 1 câu phát biểu kiểu ù ù cạc cạc!!!


Nguyên nhân
+ Hàm trong C ko hề có tham biến, hàm trong C đều hoạt động theo nguyên tắc sau :
Khi gọi hàm, 1 bản sao của tham số được tạo ra (cấp phát vùng nhớ mới, copy giá trị sang. quá trình này theo giáo trình của đại học FPT gọi là shadow copy, là 1 yếu tố cần quan tầm, 1 C/C++ Developer đừng bao giờ quên điều này), và hàm sẽ làm việc với bản sao này
(trong C++ nó sẽ dùng hàm tạo sao chép để tiến hành quá trình shadow copy này)


+ Vậy khi làm việc với con trỏ thì hàm làm thế nào
vâng, hàm vẫn cứ làm theo nguyên tắc 1 và 1 bản sao của con trỏ được tạo ra, và hàm làm việc với bản sao hàm, và trước khi gọi hàm, con trỏ trỏ vào đâu thì nó vẫn được trỏ vào đấy chứng minh :

C++ Code:
  1. #include <iostream>
    using namespace std;
  2. // Check gia tri cua con tro truoc va sau khi goi ham
  3. int ham(int *a)
    {
    *a = 2; 
    a++;
    return *a;
    }


    int main()
    {
    int c = 5;
    int *b = &c;
    cout << "Dia chi truoc khi goi ham = " << b << endl;
    ham(b);
    cout << "Dia chi sau khi goi ham = " << b << endl;

    system("pause");
    return 0;
    }


Kết quả sau khi chạy chương trình trên



VI. Vậy tôi phải làm thế nào để mà thay đổi giá trị của 1 con trỏ qua 1 hàm
Vâng, hôm nay có người bạn hỏi mình như vậy, hì hì, lại nhớ ra bài này mình chưa trả lời, vậy nên tôi đề xuất ra đây 2 cách để có thể thay đổi giá trị của 1 con trỏ qua 1 hàm 
Cách 1 : dùng tham chiếu trong C++
C++ Code:
  1. void ham(int *&a)
  2. {
  3.     a=new int[100];
  4. }
  5. void ham(int **&a)
  6. {
  7.     a=new int*[100];
  8. }
xin chú ý là * đứng trước &

Cách 2 : up level của * dùng con trỏ cấp cao hơn con trỏ hiện tại
Cách 2 này mình chỉ demo thôi, bạn cần phải đọc chi tiếp ở chap con trỏ đa cấp
C++ Code:
  1. #include <stdio.h>
  2. #include <conio.h>
  3.  
  4. void ham(int **a)
  5. {
  6.     *a=(int*)malloc(100*sizeof(int));
  7.     //a[0]=(int*)malloc(100*sizeof(int));
  8.     // 2 cach nay nhu nay
  9. }
  10.  
  11. void main()
  12. {
  13.     int *a;
  14.     ham(&a);
  15.  
  16.     free(a);
  17. }



Tip: để có thể thay đổi được giá trị địa chỉ của con trỏ sau khi thưc hiện hàm con,
Lúc đó phải khai báo tham số truyển vào là Reference to Pointer (giá trị địa chỉ của con trỏ)

như sau:

chỉ thay chương trình trên một chút:

C++ Code:
  1. #include <iostream>
    using namespace std;
  2. // Check gia tri cua con tro truoc va sau khi goi ham
  3. int ham(int *&a)
    {
    *a = 2; 
    a++;
    return *a;
    }


    int main()
    {
    int c = 5;
    int *b = &c;
    cout << "Dia chi truoc khi goi ham = " << b << endl;
    ham(b);
    cout << "Dia chi sau khi goi ham = " << b << endl;

    system("pause");
    return 0;
    }
Kết quả sau khi chạy chương trình: -> địa chỉ của biến con trỏ b đã được thay đổi






Bỏ qua phần tip trên, ta đi tiếp:

+ Vậy tại sao lại có sự thay đổi và tại sao lại sử dụng con trỏ trong hàm? Con trỏ ko thay đổi thì cái gì thay đổi được ?
vâng, các bạn chú ý nhé, giá trị nằm trong vùng nhớ trỏ đến thay đổi. Vâng đúng thế đấy bạn à, do biến của ta nằm trong vùng nhớ được trỏ đến nên nó được thay đổi


C++ Code:
  1. #include <stdio.h>
  2. #include <conio.h>
  3.  
  4. int ham(int *a)
  5. {
  6.     *a=2; // làm việc với địa chỉ nhận được
  7. }
  8. void main()
  9. {
  10.     int n;
  11.     ham(&n);// truyền địa chỉ của n vào đây
  12.     // do đó sau hàm này n =2
  13.     getch();
  14. }

Kết quả giá trị nằm trong vùng địa chỉ của n được thay đổi NHƯNG địa chỉ thì không thay đổi










1 comments :