Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Trang 1 của 3 123 CuốiCuối
Kết quả 1 đến 10 của 21
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    char *tenham(char *s) {khi return địa chỉ của mảng 1 chiều lại cho kết quả khác với return một con trỏ}Tại sao?

    ĐỀ BÀI: viết hàm left,right,mid.
    [CODE 1]các hàm trả về con trỏ
    Mã:
    #include<stdio.h>
    #include<conio.h>
    #include<malloc.h>
    #include<string.h>
    char *left(char *pst,int n );
    char *right(char *pst,int n );
    char *mid(char *pst,int n,int m);
     void main()
    {
    int n,m;
    char pst[100];
    printf("Nhap so ky tu can in ra man hinh: ");
    scanf("%d",&n);
    fflush(stdin);
    printf("nhap chuoi ky tu bat ky: ");
    gets(pst);
    printf("%s
    ",left(pst,n));
    printf("%s",right(pst,n));
    printf("
    m = ");
    scanf("%d",&m);
    printf("%s",mid(pst,n,m));
    getch();
    }
    // hàm left in ra màn hình n ký tự từ trái sang phải(từ pf[0]);
    char *left(char *pst,int n )
    {
    int i = 0;
    char *pf;
    pf = (char*)malloc(n);
    for(i=0;i<n;i++)
    {
    pf[i] = pst[i];
    }
    pf[n] = '\0';
    return pf;
    }
    //hàm right in ra n ký tự từ phải sang trái. Tính từ ký tự cuối cùng của chuỗi
    char *right(char *pst,int n )
    {
    int i = 0,a;
    char *pr;
    pr = (char*)malloc(n);
    a = strlen(pst);
    for(i=n;i>=0;i--)
    {
    pr[i] = pst[a];
    a--;
    }
    return pr;
    }
    //In ra màn hình từ ký tự thứ n trong chuỗi ký tự và in ra m ký tự
    char *mid(char *pst,int n,int m)
    {
    int c;
    char *pm;
    pm = (char *)malloc(m);
    for(int i = 0;i<n;i++)
    {
    pm[i] = pst[m];
    m++;
    }
    pm[n] = '\0';
    return pm;
    }
    ______________________________________

    [CODE 2 ]các hàm trả về địa chỉ của mảng.
    Mã:
    #include<stdio.h>
    #include<conio.h>
    #include<malloc.h>
    #include<string.h>
    char *left(char *pst,int n );
    char *right(char *pst,int n );
    char *mid(char *pst,int n,int m);
     void main()
    {
    int n,m;
    char pst[100];
    printf("Nhap so ky tu can in ra man hinh: ");
    scanf("%d",&n);
    fflush(stdin);
    printf("nhap chuoi ky tu bat ky: ");
    gets(pst);
    printf("%s
    ",left(pst,n));
    printf("%s",right(pst,n));
    printf("
    m = ");
    scanf("%d",&m);
    printf("%s",mid(pst,n,m));
    getch();
    }
    // hàm left in ra màn hình n ký tự từ trái sang phải(từ pf[0]);
    char *left(char *pst,int n )
    {
    int i = 0;
    char pf[100];
    //pf = (char*)malloc(n);
    for(i=0;i<n;i++)
    {
    pf[i] = pst[i];
    }
    pf[n] = '\0';
    return pf;
    }
    //hàm right in ra n ký tự từ phải sang trái. Tính từ ký tự cuối cùng của chuỗi
    char *right(char *pst,int n )
    {
    int i = 0,a;
    char pr[100];
    //pr = (char*)malloc(n);
    a = strlen(pst);
    for(i=n;i>=0;i--)
    {
    pr[i] = pst[a];
    a--;
    }
    return pr;
    }
    //In ra màn hình từ ký tự thứ n trong chuỗi ký tự và in ra m ký tự
    char *mid(char *pst,int n,int m)
    {
    int c;
    char pm[100];
    //pm = (char *)malloc(m);
    for(int i = 0;i<n;i++)
    {
    pm[i] = pst[m];
    m++;
    }
    pm[n] = '\0';
    return pm;
    }
    ______________________________
    Mình được học là con trỏ và mảng có liên hệ với nhau.Địa chỉ của mảng củng là tên của mảng vậy tại sao khi mình return tên mảng; thì lại cho ra kết quả in ra màn hình sai.
    Lúc đầu mình chạy bài này(code 2) bằng DEV C thì hàm right và hàm mid lại chạy đúng nhưng hàm left lại chạy sai.Sau đó mình chuyển sang chạy chương trình bằng visual stdio 2010 thì cả 3 hàm đều in ra màn hình các ký tự bậy bạ(Nên mình nghỉ bài này mình làm sai).Nhưng CODE 1 tức là các hàm mình trả về con trỏ thì cả 2 chương trình DEV C và VISUAL STDIO 2010 đều chạy đúng.

    Câu hỏi mình đặt ra ở đây là tại sao code 1 mình chạy đúng còn code 2 lại sai( có thể chương trình đúng nhưng lại sai cơ bản gì đó mà mình không biết).
    _______________________________
    Trong quá trình chạy chương trình bằng CODE 1 mình cho chạy từng dòng code 1(F10 trong visual stdio) thì mình phát hiện như thế này:
    char *p;
    ->int i=0,j;
    Khi chương trình chạy đến mũi tên thì trong ô Value con trỏ p như sau:
    - p 0xcccccccc <Bad Ptr> char *

    CXX0030: Error: expression cannot be evaluated// vậy thông báo này là như thế nào?
    P.s Bài viết của mình có thể khó hiểu do cách diễn đạt của mình nên mong các bạn thông cảm. Nếu các bạn không hiểu chỗ nào có thể trả lời bên dưới để mình giải thích lại.
    Cảm ơn các bạn đã ghé thăm và giúp đở.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Khác.
    Và bạn mất 4 byte :|

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Bạn #huycan nói đúng rồi đấy, bạn dùng static trước khai báo kích thước mảng. Bạn sai cũng là đều dễ hiểu, bởi bì code 2 của bạn là 1 mảng, bạn không thể return trả về nó như mảng động ở code 1 được. Nó chỉ trả về giá trị đầu tiên của mảng mà thôi. Bạn cũng phải dùng hàm free để giải phóng ram nữa chứ (~,~)

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    thêm keyword static vào thì ko đúng nghĩa cho lắm. Mảng static cho hàm f thì chỉ hàm f xài thôi, sao main lại được phép rờ vào được. Hơn nữa chỉ return được 1 địa chỉ duy nhất thay vì nhiều địa chỉ khác nhau, nó na ná như đem cái mảng trong hàm f thành mảng global rồi.

    1 là cấp phát động rồi return về, 2 là truyền con trỏ từ main vào hàm f, 3 là định nghĩa 1 struct chứa mảng rồi return struct đó.

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi prog10
    Khác.
    Và bạn mất 4 byte :|
    Có phải mất 4 byte được cấp phát ở lần 1 không lý do con trỏ p đã trỏ đến vùng nhớ được cấp phát lần 2 nên mất.

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Mình chưa học static gì đó. Trước giờ toàn xài DEV C cho nhẹ thấy chạy đúng ai ngờ mấy hôm nay chuyển sang chạy visual stdio thì toàn chạy sai. Nên giờ mới chẳng hiểu sao đây?. Giảng viên dạy mình thấy bài làm chạy đúng thì cho điểm rồi bỏ đi chứ có phân tích code sai đúng gì đâu.
    Ủa mà mình nhớ các biến trong hàm khi làm việc thì được cấp phát bộ nhớ mà khi thoát ra khỏi hàm thì giải phòng. Vậy thì mảng với cấp phát động cũng giải phóng luôn chứ.
    P.s: Mình chỉ mới học năm 1 nên trình còn gà hỏi mấy cái còn cơ bản nhưng mong các bạn giúp đỡ. [IMG]images/smilies/biggrin.png[/IMG]

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi taibongv001
    Có phải mất 4 byte được cấp phát ở lần 1 không lý do con trỏ p đã trỏ đến vùng nhớ được cấp phát lần 2 nên mất.
    đúng rồi.

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi INTP
    biến được cấp phát bằng malloc thì ko tự giải phóng khi thoát khỏi thân hàm. Biến này nằm trên heap.

    biến được cấp phát bình thường, ko đụng tới malloc thì thoát khỏi thân hàm là mất luôn. Biến này nằm trên stack. Có thể nó ko mất liền, nhưng gọi hàm khác nữa thì nó sẽ mất.

    gán static cho biến thì biến này ko nằm trên heap lẫn stack, mà nằm trên vùng data hoặc bss. Loại biến này chỉ được cấp phát 1 lần duy nhất trong suốt thời gian chương trình chạy, mặc dù có gọi hàm f đó 100 lần thì biến static x cũng chỉ nằm ở 1 địa chỉ. So với biến nằm trên stack/heap thì mỗi lần gọi là mỗi lần x được cấp phát địa chỉ mới, có thể trùng địa chỉ cũ nhưng ko bảo đảm 100% như static.



    Vì biến nằm trên heap ko tự động giải phóng nên (mảng) x có thể được cấp phát trong hàm f1, rồi truyền con trỏ tới x sang hàm f2, f3, f4, v.v..., coi như là truyền được mảng từ hàm này sang hàm khác. Nhược điểm là truyền 1 hồi mà quên giải phóng nó thì chương trình ngốn bộ nhớ khá nhiều. Vd hàm f1 cấp phát mảng int[1000] = malloc và trả về mảng này. Gọi hàm f1 trong 1 vòng lặp trong main, lặp 100 ngàn lần mà kết thúc vòng lặp ko free mảng được f1 cấp phát thì bộ nhớ vẫn chứa 100 ngàn x 1000 = 100 triệu int ~ 400MB bộ nhớ, trong khi nếu free mảng f1 cấp phát trong vòng lặp thì chỉ tốn cỡ 4KB. Hay vd khác khi viết game, 1 giây vẽ 60 lần (60 FPS), mỗi lần hình P (mảng unsigned int 2 chiều, 100x100 pixels) được tạo từ hàm f1, trong đó P được cấp phát = malloc trong f1. Trong main chạy game loop mà ko free hình P thì 1 vòng lặp tốn khoảng 40KB bộ nhớ, 1 giây ngốn 2.5MB bộ nhớ, chạy được 1 phút thì ngốn khoảng 150MB bộ nhớ... Game thì có malloc cho cỡ 100 hình như vậy, quên 1 hình thì ko biết lỗi nó nằm ở malloc thằng nào...
    => viết chữ malloc xong thì phải viết chữ free ở đâu đó liền
    Vậy có nghĩa là mảng cũng bị giải phóng khi kết thúc hàm phải không vậy?

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    biến được cấp phát bằng malloc thì ko tự giải phóng khi thoát khỏi thân hàm. Biến này nằm trên heap.

    biến được cấp phát bình thường, ko đụng tới malloc thì thoát khỏi thân hàm là mất luôn. Biến này nằm trên stack. Có thể nó ko mất liền, nhưng gọi hàm khác nữa thì nó sẽ mất.

    gán static cho biến thì biến này ko nằm trên heap lẫn stack, mà nằm trên vùng data hoặc bss. Loại biến này chỉ được cấp phát 1 lần duy nhất trong suốt thời gian chương trình chạy, mặc dù có gọi hàm f đó 100 lần thì biến static x cũng chỉ nằm ở 1 địa chỉ. So với biến nằm trên stack/heap thì mỗi lần gọi là mỗi lần x được cấp phát địa chỉ mới, có thể trùng địa chỉ cũ nhưng ko bảo đảm 100% như static.



    Vì biến nằm trên heap ko tự động giải phóng nên (mảng) x có thể được cấp phát trong hàm f1, rồi truyền con trỏ tới x sang hàm f2, f3, f4, v.v..., coi như là truyền được mảng từ hàm này sang hàm khác. Nhược điểm là truyền 1 hồi mà quên giải phóng nó thì chương trình ngốn bộ nhớ khá nhiều. Vd hàm f1 cấp phát mảng int[1000] = malloc và trả về mảng này. Gọi hàm f1 trong 1 vòng lặp trong main, lặp 100 ngàn lần mà kết thúc vòng lặp ko free mảng được f1 cấp phát thì bộ nhớ vẫn chứa 100 ngàn x 1000 = 100 triệu int ~ 400MB bộ nhớ, trong khi nếu free mảng f1 cấp phát trong vòng lặp thì chỉ tốn cỡ 4KB. Hay vd khác khi viết game, 1 giây vẽ 60 lần (60 FPS), mỗi lần hình P (mảng unsigned int 2 chiều, 100x100 pixels) được tạo từ hàm f1, trong đó P được cấp phát = malloc trong f1. Trong main chạy game loop mà ko free hình P thì 1 vòng lặp tốn khoảng 40KB bộ nhớ, 1 giây ngốn 2.5MB bộ nhớ, chạy được 1 phút thì ngốn khoảng 150MB bộ nhớ... Game thì có malloc cho cỡ 100 hình như vậy, quên 1 hình thì ko biết lỗi nó nằm ở malloc thằng nào...
    => viết chữ malloc xong thì phải viết chữ free ở đâu đó liền

  10. #10
    Trích dẫn Gửi bởi taibongv001
    Vậy có nghĩa là mảng cũng bị giải phóng khi kết thúc hàm phải không vậy?
    Mảng tĩnh thì đúng vậy.

 

 
Trang 1 của 3 123 CuốiCuối

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •