Announcement

Collapse
No announcement yet.

con trỏ trong C phần 2 - và các phần tiếp theo

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • 11520327
    replied
    khà khà thầy thiếu câu lệnh return trong hàm main.
    em cài hđh 32bit nên kết quả xuất ra là 6422610. e tách số này ra là: 64 226 1 0
    số 123456 thuộc kiểu integer nên lưu trong bộ nhớ như sau (4byte):
    00000000 00000001 11100010 01000000 thứ tự dãy tính từ trái qua sẽ là dãy 1, 2,3 ,4.
    biến con trỏ pa thuộc kiểu char có kích thước 1 byte.
    khi gán pa=(unsigned char*)&a thì pa sẽ trỏ tới dãy 1. pa+1 trỏ tới dãy 2, pa+2 trỏ tới dãy 3... vậy suy ra vòng for đã duyệt hết cả 4 dãy trên thông qua con trỏ pa và chỉ số i. ở đây, câu lệnh printf có đặc tả %d, tức là lấy giá trị nguyên nên trình biên dịch sẽ đổi các dãy nhị phân trên thành các số nguyên tương ứng và in lên màn hình. các bạn chú ý là vòng lặp for duyệt 1 lần 8byte( kích thước kiểu char).
    dãy đâu tiên là số 0. dãy thứ hai là số 1. dãy thứ ba là số 226. dãy cuối cùng là 64.
    vậy kết quả thu được là 6422610. nếu các bạn sửa câu lệnh printf thành printf("%d\t", *(pa+1)) thì sẽ thấy rõ kết quả.

    Leave a comment:


  • truonganpn
    replied
    Originally posted by 11520327 View Post
    mọi người tiếp tục cho bình luận nha, vì mục đích chung là kiến thức...
    Các bạn thảo luận bài này cũng đã rõ rồi. Next qua bài mới đi, tôi ra đề nhá:

    PHP Code:
    #include<stdio.h>

    int main()
    {
        
    int a 123456;
        
    unsigned charpa = (unsigned char* )&a;
        for (
    int i 0i<sizeof(a); i++)
        
    printf("%d\n", *(pa+i));
        return 
    0;

    Cũng yêu cầu đoán xem code này xuất ra kết quả là gì và tại sao như vậy? Môi trường chạy là CPU theo kiến trúc x86_64 nhá. Các bạn chú ý là conio.h không phải thư viện chuẩn của C và việc thêm cái lệnh để dừng chương trình là không cần thiết nha.
    Last edited by truonganpn; 06-10-2012, 15:15.

    Leave a comment:


  • 11520327
    replied
    mọi người tiếp tục cho bình luận nha, vì mục đích chung là kiến thức...

    Leave a comment:


  • 11520327
    replied
    đoạn code đề bài:
    PHP Code:
    #include<stdio.h> 
    #include<conio.h> 

    void Tag(int *a

        
    a=new int(); 
    }; 
    int main() 

        
    int *p=NULL
        
    Tag(p); 
        *
    p=6

        
    printf("%d", *p); 
        
    getch(); 
        return 
    0

    Lỗi 1: C không có toán tử new.
    Lỗi 2: chương trình chạy không đúng. Khi gọi hàm Tag(p) thì trình biên dịch sẽ tạo ra a là bản sao của p. nếu p chưa được cấp phát thì a và p chẳng có liên quan gì đến nhau,(ngược lại a và p sẽ trỏ đến cùng 1 vùng nhớ), nói cách khác, mọi thao tác trên a đều vô nghĩa với p. do đó, hàm Tag(p) không cấp phát cho p vùng nhớ nào cả, vùng nhớ đó cấp phát cho a và tồn tại ngay cả khi a bị hủy. p không được cấp phát cho nên câu lệnh *p=6 sẽ bị lỗi.

    giải pháp:
    PHP Code:
    #include<stdio.h> 
    #include<conio.h> 
    #include<malloc.h>

    void Tag(int **a

        *
    a=(int*)malloc(sizeof(int));
    }; 
    int main() 

        
    int *p=NULL
        
    Tag(&p); 
        *
    p=6
        
    printf("%d", *p); 
        
    getch(); 
        return 
    0

    để cho dễ hiểu, các bạn cứ hình dung trong hàm main ta có 1 biến int **temp=&p; và ta truyền biến temp này cho hàm Tag(temp); khi hàm Tag(temp) thực hiện thì trình biên dịch sẽ tạo ra 1 bản sao của temp, đó là biến cục bộ a. ta có thể biểu diễn 1 cách nôm na như sau: int **a=temp.
    ta cũng biết, phép toán gán bằng trong con trỏ có thể hiểu là đưa con trỏ bên trái trỏ đến vùng nhớ mà con trỏ bên phải đang nắm giữ. tức là theo ví dụ trên, temp trỏ tới biến p, a=temp, suy ra a cũng trỏ tới p. tuy a chỉ là biến cục bộ, nhưng do a trỏ tới p nên a có thể thực hiện những thao tác có hiệu lực trên p, như cấp phát cho p chẳng hạn. và sau khi Tag() thực hiện xong, thì biến cục bộ a mất, nhưng vùng nhớ cấp phát cho p vẫn tồn tại, do đó, p đã được cấp phát. nói khác đi, hàm Tag() đã thực hiện được nhiệm vụ cấp phát cho p.
    trong lời gọi hàm Tag(&p) trên, thay vì truyền temp thì chúng ta làm ngắn gọn hơn nhưng ý nghĩa cũng giống như trên.
    Last edited by 11520327; 06-10-2012, 09:05.

    Leave a comment:


  • 09520019
    replied
    Originally posted by 11520327 View Post
    khi truyền kiểu tham trị thì khi gọi hàm sẽ có 1 bản sao của x được tạo ra, và hàm thao tác trên cái bản sao này, làm gì có chuyện mà x chui ra chui vào hàm như vậy anh!
    Sao em không nói là khi truyền kiểu tham trị thì gọi hàm sẽ có 1 bản sao của x được tạo ra nằm trên stack, bên trong hàm sử dụng phần giá trị nằm trong stack này, khi ra khỏi hàm thì phần stack cấp cho hàm sẽ bị xóa, nên giá trị đã sử dụng bên trong hàm sẽ bị mất ?

    Không hiểu là em bắt bẻ cái gì khi anh đã ghi 1 câu to đùng: Pass by value !!!
    Anh cũng đã nói rõ x bên trong hàm có thể thay đổi, nhưng ra ngoài hàm thì x (biến đã truyền), có giá trị trước khi nó được truyền thì có gì sai ? Nói chung là anh không thích diễn đạt theo nghĩa hàn lâm khô cứng. Em thích diễn đạt theo ý nào tùy em thích. Lần này anh trả lời ngắn gọn thôi: pass by value, không biết thì google.

    Và túm luôn lại là anh vẫn chưa thấy em post đáp án ?

    Leave a comment:


  • 08520016
    replied
    Originally posted by 11520327 View Post
    khi truyền kiểu tham trị thì khi gọi hàm sẽ có 1 bản sao của x được tạo ra, và hàm thao tác trên cái bản sao này, làm gì có chuyện mà x chui ra chui vào hàm như vậy anh!
    thì ý bạn Châu là thế đó.
    C chỉ có truyền tham trị thôi, nhớ vậy là đc.

    Leave a comment:


  • 11520327
    replied
    sau khi truyền hàm abc(x) thì x vào trong hàm có thể thay đổi, nhưng ra bên ngoài hàm thì x có giá trị như trước khi nó được truyền
    khi truyền kiểu tham trị thì khi gọi hàm sẽ có 1 bản sao của x được tạo ra, và hàm thao tác trên cái bản sao này, làm gì có chuyện mà x chui ra chui vào hàm như vậy anh!

    Leave a comment:


  • 09520019
    replied
    Originally posted by 11520327 View Post
    câu này của a khó hiểu quá. biến được truyền là biến gì?
    Theo cách truyền bằng tham trị thì giá trị của biến dùng làm đối số cho hàm sẽ không bị thay đổi.
    sau khi truyền hàm abc(x) thì x vào trong hàm có thể thay đổi, nhưng ra bên ngoài hàm thì x có giá trị như trước khi nó được truyền

    Còn 1 ý để ám chỉ là cách 2 bạn này là sai

    Originally posted by 10520191 View Post
    ......
    void Tag(int* &a)
    {
    a = new int();
    }
    Vì trong C không có kiểu truyền &, mà kiểu truyền & (vd int abc(int &x)) là kiểu truyền của C++, gọi là truyền tham chiếu

    Leave a comment:


  • 11520327
    replied
    Originally posted by 09520019 View Post
    Trong C, chỉ có 1 cách truyền tham số, gọi là truyền giá trị. Giá trị của biến được truyền sẽ bị mất sau khi ra khỏi hàm..
    câu này của a khó hiểu quá. biến được truyền là biến gì?
    Theo cách truyền bằng tham trị thì giá trị của biến dùng làm đối số cho hàm sẽ không bị thay đổi.

    Leave a comment:


  • 09520019
    replied
    Originally posted by 11520327 View Post
    a giải thích rõ hơn được không?
    Giải pháp thì chắc mọi người nói rồi ha, nếu cần thì mình sẽ viết lại là
    Code:
    void Tag(int **a) 
    { 
        (*a) = (int*) malloc(sizeof(int));
    };
    OK, còn giải thích, ngắn gọn là vầy

    Trong C, chỉ có 1 cách truyền tham số, gọi là truyền giá trị. Giá trị của biến được truyền sẽ bị mất sau khi ra khỏi hàm.
    int* a là kiểu con trỏ, kiểu giá trị là int *, cho nên kiểu giá trị int * sẽ bị mất sau khi ra khỏi hàm tag.
    Trong C, không phải cứ truyền con trỏ, là giá trị của nó sẽ thay đổi sau khi ra khỏi hàm

    Còn dài dòng hơn tí thì
    1 ví dụ dễ hiểu là so sánh việc truyền
    Code:
    void tag1(int a)
    {
        a = 5;
    }
    
    void tag2(int *a)
    {
        *a = null;
    }
    
    int main()
    {
        int a = 7;
        int *x = &a;
        tag1(a);
        tag2(b);
    }
    Dài dòng hơn nữa thì
    Bạn muốn đổi giá trị của 1 biến nào đó trong C, thì bạn phải truyền con trỏ cấp cao hơn kiểu con trỏ mà bạn dùng ít nhất là 1 bậc, vì trong C luôn luôn truyền giá trị, nếu bạn truyền con trỏ có cùng cấp thì nó sẽ bị mất do nó ko thể lưu giá trị đó được.
    Last edited by 09520019; 05-10-2012, 01:03.

    Leave a comment:


  • 11520327
    replied
    tiêu đề nói là con trỏ trong C mà sao hàm cấp bộ nhớ động lại của C++ thế, lập trình kiểu này thì văng hết!
    cảm ơn bạn đã nhắc nhở, chỗ này do mình không để ý.

    Leave a comment:


  • 11520327
    replied
    ra khỏi hàm biến con trỏ cục bộ bị hủy
    Có không bị hủy em nha , nó vẫn tồn tại đấy--> cái này gọi là memory leak
    2 ý trên có chút hiểu nhầm. biến cục bộ bị hủy, vùng nhớ cấp phát cho biến cục bộ không bị hủy.
    khi chạy chương trình thì kết quả như thế nào, giải thích tại sao có kết quả như vậy và đưa ra giải pháp nếu có.
    code em đưa ra là sai, thế nên phần yêu cầu mới có cái "giải pháp".
    Last edited by 11520327; 04-10-2012, 23:41.

    Leave a comment:


  • 08520016
    replied
    Originally posted by 10520191 View Post
    Code đầu:
    void Tag(int *a)
    {
    a=new int();
    };
    -> cấp phát như vậy tức là cấp phát cho biến con trỏ cục bộ (chứ ko phải cấp phát cho biến truyền vào), ra khỏi hàm biến con trỏ cục bộ bị hủy. Thế nên biến truyền vào chưa đc cấp phát :happy:
    Code sau: cấp phát như mình, tức là cấp phát cho chính vùng nhớ của con trỏ truyền vào. Thế nên ra khỏi hàm con trỏ truyền vào có giá trị (tức là vùng nhớ mới đc cấp phát).
    Code mà thớt đưa ra thì đúng là lỗi thật.Vì
    void Tag(int *a)
    {
    a=new int();
    };
    --> CON trỏ a sẽ đc truyền = tham trị nên khi
    int *p=NULL;
    Tag(p);
    *p=6;
    -> giá trị trong con trỏ p sẽ đc sao chép sang vùng nhớ mới , sau đó vùng nhớ mới này sẽ đc truyền vào hàm Tag , do đó tag chỉ tác động đến bản sao của p
    Vậy là khi *p=6 sẽ bị lỗi , vì ta chưa cấp phát bộ nhớ cho p.

    -Còn riêng đoạn này:
    Originally posted by 10520191 View Post
    Code đầu:
    void Tag(int *a)
    {
    a=new int();
    };
    -> cấp phát như vậy tức là cấp phát cho biến con trỏ cục bộ (chứ ko phải cấp phát cho biến truyền vào), ra khỏi hàm biến con trỏ cục bộ bị hủy. Thế nên biến truyền vào chưa đc cấp phát \
    --> Có không bị hủy em nha , nó vẫn tồn tại đấy--> cái này gọi là memory leak

    Leave a comment:


  • 11520537
    replied
    Originally posted by 11520327 View Post
    phần tiếp theo của bài viết " con trỏ trong C".
    đoạn code:
    PHP Code:
    #include<stdio.h>
    #include<conio.h>

    void Tag(int *a)
    {
        
    a=new int();
    };
    int main()
    {
        
    int *p=NULL;
        
    Tag(p);
        *
    p=6;

        
    printf("%d", *p);
        
    getch();
        return 
    0;

    hỏi: khi chạy chương trình thì kết quả như thế nào, giải thích tại sao có kết quả như vậy và đưa ra giải pháp nếu có.
    xin các bạn lưu ý là mình chỉ thảo luận về con trỏ, những nội dung khác không liên quan đến phần này, xin viết ở topic khác.
    nè bạn! tiêu đề nói là con trỏ trong C mà sao hàm cấp bộ nhớ động lại của C++ thế, lập trình kiểu này thì văng hết!

    Leave a comment:


  • 11520327
    replied
    khi bạn muốn thay đổi giá trị của một biến nào đó thông qua một hàm thì bạn truyền địa chỉ của biến đó vào danh sách đối số của hàm
    a giải thích rõ hơn được không?

    Leave a comment:

LHQC

Collapse
Working...
X