Friday, 29 October 2010

[Project] Pointer in C

Chủ đề tuần này: post lên những gì bạn hiểu biết, giảng cho mọi người về con trỏ trong C. Comment vào dưới bài này! Mọi code ctrình minh họa hãy paste lên pastebin(có ở list tool bên tay phải của trang chính) và đưa link vào đây.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Trước khi vào nội dung, tớ sẽ đưa ra 2 khái niệm là declare và  initialize. Và kể cả trong các bài viết sau cũng sẽ khong dịch 2 từ này ra Tiếng Việt.
1. Declare: công bố hay khai báo(biến)
ví dụ này declare một biến tên là a:
 int a;
2. Initialize: khởi tạo giá trị ban đầu (hay gán giá trị đầu tiên cho biến). Đây chính là cách viết đầy đủ của từ Init
VD:
int a;//Declare
a=5;//Initialize



1.Định nghĩa:
- con trỏ là biến chứa(có nội dung là) địa chỉ của biến khác.
- Thực không có gì là biến con trỏ cả. Chỉ có một loại biến duy nhất. Và chúng khác nhau ở kiểu (int float...)
Từ "pointer variable" (biến con trỏ) thật ra mang nghĩa là "variable of a pointer type" (biến có kiểu pointer) Vậy ta dùng từ biến con trỏ với nghĩa là biến có kiểu con trỏ.





2. Khởi tạo một con trỏ. (Declaration)
VD:
int *conga;
int convit;
- ở đây biến convit có kiểu int. còn biến conga co kiểu int *. Hãy hiểu int * ở đây là một phép ghép
int ở 1 bên, *conga ở một bên. khi gặp nhau thì * kết hợp với int thành kiểu int *.

như vậy ta có thể tạo 2 con trỏ bằng cách:
int *p;
int *q;

hoặc
int *p,*q;
chứ không phải là
int *p,q;

Tưởng tượng ở đây là dấu * là 1 con chó, dấu phẩy là 1 bức tường. con chó không vượt đượt hàng rào nên không cắn được người q :D hè hè

3. Truy cập giá trị được trỏ đến
3.1 VD:
int *p;
p=45;
Đoạn code trên sẽ bị lỗi, bởi khi p là 1 biến trỏ thì nội dung của biến này là địa chỉ của 1 biến nào đó khác.
Đoạn code trên sẽ gán cho p trỏ đến địa chỉ 45 và ta không biết là địa chỉ 45 là ở đâu. Chương trình cố gắng truy cập đến ô này và kết quả là sẽ bị lỗi.
Khi compile thì compiler thường cảnh báo bạn việc gán một giá trị int cho 1 biến trỏ:
“warning: initialization makes pointer from integer without a cast”

Vậy để truy cập đ giá trị được trỏ đến ta phải dereference nó.

3.2 Dereferencing
Từ dereference áp dụng đối với con trỏ với nghĩa là truy  cập biến hay ô nhớ mà con trỏ trỏ tới.
vD:
#include
int main()
{
    int b=5,*a;    /*Declare biến b và init nó =5, declare biến con trỏ a */
    a=&b;//gán cho a địa chỉ của b <=> trỏ a đến b
    printf("%d",*a);//in ra mà giá trị a trỏ đến.
    return 1;
}


Toán tử dereference(*) tim kiếm value tồn tại tại 1 địa chỉ.
Vậy: khi x đã là 1 biến con trỏ thì x chứa địa chỉ, còn *x chứa giá trị mà con trỏ trỏ đến. Trong phép gán, nếu *x đứng bên phải dấu bằng, * sẽ là tóan tử "load" địa chỉ x; còn nếu *x đứng bên trái dấu bằng thì * là tóan tử "store" "vế phải" vào địa chỉ x
 

12 comments:

  1. Nếu p là tên của 1 biến con trỏ, thì *p là đối tượng đang được trỏ đến bởi p.
    Ta gọi p là pointer còn *p là pointee của p. *p có thể được dùng như tên của 1 biến.

    địa chỉ của 1 đối tượng được biểu thị bằng tên của đối tượng.
    Địa chỉ của x đc biểu thị bởi &x(giá trị trỏ đến....)


    Để cấp không gian nhớ, ta dùng hàm malloc() (Memory allocator) có trong thư viện

    Trỏ đến x bằng cách gán &x cho q :
    q=&x;
    Có thể truy cập nội dung của x qua biến con trỏ bỏi *q

    int * const coptr = &x
    theo thứ tự ưu tiên có thể viết lại như sau cho dễ hiểu
    int *(const coptr)=&x
    Hiểu là: coptr là 1 con trỏ hằng, với pointee là 1 số kiểu int.

    const int * ptrcon;
    viết lại thành (const int)* ptrcon;
    nghĩa là : pointee của ptrcon là 1 hằng số int;

    a[0] <=> *a
    a[3] <-> *(a+3)
    3 ở đây là 3 lần độ dài của một type.
    &a[1]-&a[0] = 1

    &*(a) <=> a
    &*(a+1)<=>a+1
    &*(a+1)-&*(a) = 1

    float *p,a[];
    p=a;
    float *q;
    q=p+3;
    print

    sizeof arrayname -> trả về 1 giá trị int là độ lớn của mảng tính theo bytes
    sizeof (type_float_int....) trả về 1 giá trị là độ lớn của kiểu tính theo bytes


    http://pastebin.com/44REP8Kx
    _____________________________
    xem sai đâu sửa hộ tớ. Comment kiểu này hơi bị bất cập

    ReplyDelete
  2. 1 con trỏ là 1 biến chứa địa chỉ của 1 biến!
    &c trả về địa chỉ của c
    p=&c //Gán địa chỉ của c cho biến p. P được gọi là trỏ đến c
    Toán tử * dùng để truy cập đến đối tượng được con trỏ trỏ tới.

    VD minh họa cách tạo 1 con trỏ và sử dụng &,*
    int x=1, y=2, z[10];
    int *ip; /*ip là 1 con trỏ trỏ đến int - có thể hiểu theo kiểu khác: tạo 1 biến *ip kiểu int như biến bình thường int a,b.... hãy nhớ *ip là 1 pointee, nó chứa giá trị, tương tự như a hay b cũng chứa giá trị.*/
    ip=&x; // ip bây giờ trỏ tới x
    y=*ip // y bây giờ bằng 1
    *ip=0// x bây giờ bằng 0
    ip=&z[0]; // ip bay giờ trỏ tới z[0]

    ReplyDelete
  3. http://boredzo.org/pointers/ sẽ cố dịch hết cái này trong vòng ngày mai @@

    ReplyDelete
  4. đọc cái này xong vẫn chưa hiểu lắm :(
    hay tại mìh chậm hiểu quá nhỉ ?

    ReplyDelete
  5. cm tiếp theo tớ đưa lên bài post luôn

    ReplyDelete
  6. trong phep' toan' bo? sung 1 phan` tu? vao` cuoi' danh sach ma` sep' Truong` viet'
    p=l;
    while (link(p)#null
    do p=link(q);link(q)=p

    neu' link(q)=p la` tro? den' p
    thi` p=link(q) nghia~ la` gi` nhi?

    cac' ban. viet' luon trong C cho minh` nhe'

    ReplyDelete
  7. code C tham khảo chạy được sẽ cố đưa lên trc thứ 3.

    mày chép sai thì hiểu cái quái j con nhợn:

    {q=L;//cho q trỏ lại đầu danh sách
    while (link(q)#NULL) //khi q không phải là phần tử cuối
    {q=link(q);}//thì chuyển sang phần tử kế tiếp
    link(q)=p;//nếu q là phần tử cuối thì gán link(q)=p -> tức q trỏ và p(phần tử cuối mới)
    Got it?
    }

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. vao` khi do' link(p)=null a`
    sao tao thay' danh sach' lien ket' giong' Stack the' nhi?

    Famihug la` thang` nao` the' , Co Dong a`
    =))

    ReplyDelete
  10. mày đang bổ sung phần tử cuôi là p thì tất nhiên link(p)=NULL rồi.

    Danh sách liên kết là cái để cài stack lên
    Mảng cũng là cái để cài stack lên.
    Chứ stack không phải là mảng hay danh sách liên kết! hiểu chưa?

    ReplyDelete
  11. hiểu rồi
    nó kiểu kiểu như thế nhưng phần tử của nó biến thiên , thêm bớt tùy ý ko như mảng , rất cơ động =))

    ReplyDelete