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

  • #16
    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!

    Comment


    • #17
      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.

      Im a british accent lover

      Comment


      • #18
        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 ?
        Khoảng cách giữa bạn và ước mơ của bạn là bao xa ?

        Comment


        • #19
          đ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.

          Comment


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

            Comment


            • #21
              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.

              Comment


              • #22
                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ả.

                Comment


                • #23
                  Originally posted by 11520327 View Post
                  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ả.
                  CPU theo kiến trúc x86_64 ý quan trọng nằm ở đây nè bạn ...

                  suy nghĩ lại rồi xóa đi cho các bạn tự tìm hiểu ^_^... chú ý là máy của các bạn thường kiểu int là 32bit, nhưng trong cái đề này thì ko chắc đâu nha :happy:

                  Mà lỡ nhiều chiện rồi cho mình nói thêm tí, mấy bạn khóa dưới khoa KTMT hay dự định vào KTMT thì nên chú ý bài này nha... bài này rất là hay đấy :byebye:
                  Last edited by 08520229; 06-10-2012, 15:34.
                  Một khẩu súng giữ hai trời Nam Bắc,
                  Một dấu chân in màu đất hai miền.

                  ------------------------------------------------------

                  Comment


                  • #24
                    Originally posted by 11520327 View Post
                    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ả.
                    Hàm không return thì nó là một "undefined behavior" thôi chứ không phải lỗi , dù sao thì cũng sửa lại cho dễ nhìn.

                    Còn một vấn đề nữa là tại sao lại ra 64 226 1 0. Tại sao không phải là 0 1 226 64? Bạn Mẫn có tô đậm một ý rồi đó, đề không thừa đâu

                    Comment


                    • #25
                      cái 0 1 226 64 hay 64 226 1 0 là do thứ tự lưu trong bộ nhớ từ phải qua trái thì phải? còn x86_64 thì em hông hiểu... tuy nhiên để đề phòng bất trắc nên em mới viết
                      em cài hđh 32bit
                      không biết là x86_64 có liên quan gì đến hđh 32 hay 64 không?
                      vậy cái x86_64 là gì thế ạ?

                      Comment


                      • #26
                        Thêm 1 chú ý nữa:
                        - Các bạn tìm hiểu 2 khái niệm Big EndianLitle Endian là sẽ biết đáp án .
                        -Và các máy Intel X86 X64 dùng Litle Endian
                        -->Tự kiếm kết quả
                        Last edited by 08520016; 06-10-2012, 15:43.

                        Im a british accent lover

                        Comment


                        • #27
                          x86_64
                          đã có thông tin:
                          Có thể hiểu một cách đơn giản như sau.
                          80.386 hay thường gọi là i386 hoặc 386 là bộ vi xử lý được Intel giới thiệu đầu tiên vào năm 1985.
                          Sau này còn nhiều bộ vi khác cùng thuộc dòng 8x.x86 và được gọi chung là x86.
                          Nói tới x86 tức là nói bộ vi xử lý 32 bit chung. Trước nó có 80.086 là 16 bit.

                          Còn về x86_64 tức là dành cho các CPU đời mới. Mở rộng từ x86 lên thành 64 bit.
                          nguồn http://www.zend.vn/forum/viewtopic.php?f=31&t=375

                          Comment


                          • #28
                            Originally posted by 11520327 View Post
                            cái 0 1 226 64 hay 64 226 1 0 là do thứ tự lưu trong bộ nhớ từ phải qua trái thì phải? còn x86_64 thì em hông hiểu... tuy nhiên để đề phòng bất trắc nên em mới viết

                            không biết là x86_64 có liên quan gì đến hđh 32 hay 64 không?
                            vậy cái x86_64 là gì thế ạ?
                            hệ điều hành 32bit của em không có liên quan gì tới vấn đề này cả. Nó chỉ có ý nghĩa là OS đó có thể cài đặt trên các bộ xử lý hỗ trợ tập lệnh cho nó (32 bit)... tức là các máycó kiến trúc tương đương x86 của intel, nên trong cái tên của OS thì bạn thấy nó ghi là x86 trong khi win 64 bit nó ghi là x64.

                            còn x86 là kiến trúc máy tính của intel sử dụng little edian... xuất hiện cùng thời với x86 thì còn có một số kiến trúc khác như MAC và Motorola dùng big edian

                            Ở các thế hệ máy cũ... một số trình complier C cho vi điều khiển vẫn giữ kiểu nguyên là 16bit , còn hiện tại cho PC thông thường là 32 bit (giống máy bạn đang sử dụng), một số là 64 bit... sự khác biệt này dẫn đến sự khác biệt của kết quả in ra gồm bao nhiêu byte. 2,4 hay 8. Trong đề là x86_64 => có lẽ ở đây ám chỉ kiểu int mặc định là 64 bit ??? cái này phải nhờ tới anh An giải đáp. Theo mình thấy thì thông thường kiểu int mặc định của trình biên dịch sẽ có cùng kích thước với kích thước thanh ghi của kiến trúc...
                            Last edited by 08520229; 06-10-2012, 16:09.
                            Một khẩu súng giữ hai trời Nam Bắc,
                            Một dấu chân in màu đất hai miền.

                            ------------------------------------------------------

                            Comment


                            • #29
                              Originally posted by 08520229 View Post
                              Ở các thế hệ máy cũ... một số trình complier C cho vi điều khiển vẫn giữ kiểu nguyên là 16bit , còn hiện tại cho PC thông thường là 32 bit (giống máy bạn đang sử dụng), một số là 64 bit... sự khác biệt này dẫn đến sự khác biệt của kết quả in ra gồm bao nhiêu byte. 2,4 hay 8. Trong đề là x86_64 => có lẽ ở đây ám chỉ kiểu int mặc định là 64 bit ??? cái này phải nhờ tới anh An giải đáp. Theo mình thấy thì thông thường kiểu int mặc định của trình biên dịch sẽ có cùng kích thước với kích thước thanh ghi của kiến trúc...
                              Đúng là cái đó ám chỉ kiến trúc 64-bit. Giữa bao la các trình biên dịch hiện tại thì chỉ có kiểu con trỏ là đảm bảo cùng kích thước với thanh ghi của kiến trúc (vì phải như vậy nó mới đảm bảo lưu trữ được địa chỉ). Còn kiểu int cơ bản thì các trình biên dịch dùng kích thước khác nhau nhưng với 2 trình biên dịch phổ biến nhất mà các bạn hay dùng là Visual C và GNU C thì kiểu int 4-byte cho cả kiến trúc 64-bit và 32-bit.

                              Comment


                              • #30
                                Originally posted by 08520229 View Post
                                hệ điều hành 32bit của em không có liên quan gì tới vấn đề này cả. Nó chỉ có ý nghĩa là OS đó có thể cài đặt trên các bộ xử lý hỗ trợ tập lệnh cho nó (32 bit)... tức là các máycó kiến trúc tương đương x86 của intel, nên trong cái tên của OS thì bạn thấy nó ghi là x86 trong khi win 64 bit nó ghi là x64.

                                còn x86 là kiến trúc máy tính của intel sử dụng little edian... xuất hiện cùng thời với x86 thì còn có một số kiến trúc khác như MAC và Motorola dùng big edian

                                Ở các thế hệ máy cũ... một số trình complier C cho vi điều khiển vẫn giữ kiểu nguyên là 16bit , còn hiện tại cho PC thông thường là 32 bit (giống máy bạn đang sử dụng), một số là 64 bit... sự khác biệt này dẫn đến sự khác biệt của kết quả in ra gồm bao nhiêu byte. 2,4 hay 8. Trong đề là x86_64 => có lẽ ở đây ám chỉ kiểu int mặc định là 64 bit ??? cái này phải nhờ tới anh An giải đáp. Theo mình thấy thì thông thường kiểu int mặc định của trình biên dịch sẽ có cùng kích thước với kích thước thanh ghi của kiến trúc...

                                Hình như x64 dùng để đánh lạc hướng hay là nêu đề bài cho đầy đủ ? Chứ chỉ có con trỏ là 64bit, còn int vẫn 32bit, kiểu long mới thay đổi từ 4bytes lên 8 bytes. Cái x64 thì không rõ ý đồ của anh An

                                ftp://gcc.gnu.org/pub/gcc/summit/200...2064%20bit.pdf

                                Editted: à rồi nêu đề bài cho rõ
                                Originally posted by truonganpn View Post
                                Đúng là cái đó ám chỉ kiến trúc 64-bit. Giữa bao la các trình biên dịch hiện tại thì chỉ có kiểu con trỏ là đảm bảo cùng kích thước với thanh ghi của kiến trúc (vì phải như vậy nó mới đảm bảo lưu trữ được địa chỉ). Còn kiểu int cơ bản thì các trình biên dịch dùng kích thước khác nhau nhưng với 2 trình biên dịch phổ biến nhất mà các bạn hay dùng là Visual C và GNU C thì kiểu int 4-byte cho cả kiến trúc 64-bit và 32-bit.
                                Originally posted by 08520016 View Post
                                Thêm 1 chú ý nữa:
                                - Các bạn tìm hiểu 2 khái niệm Big EndianLitle Endian là sẽ biết đáp án .
                                -Và các máy Intel X86 X64 dùng Litle Endian
                                -->Tự kiếm kết quả
                                Cái gợi ý của anh Tàu coi như đáp án roài
                                Last edited by 09520019; 06-10-2012, 16:44.
                                Khoảng cách giữa bạn và ước mơ của bạn là bao xa ?

                                Comment

                                LHQC

                                Collapse
                                Working...
                                X