SlideShare ist ein Scribd-Unternehmen logo
1 von 34
ĐẠI HỌC CÔNG NGHỆ THÔNG TIN - ĐHQG Tp HCM – SE05




   CON TRỎ TRONG NGÔN NGỮ
             C/C++


            SE-PRO GROUP

                                               1
NỘI DUNG:


        DẪN NHẬP
        CON TRỎ CƠ BẢN
        CON TRỎ NÂNG CAO
       TÀI LIỆU THAM KHẢO




                             2
DẪN NHẬP                                                 Byte 2n
                                    Memory
                                     (RAM)
                              Win n bit thì




                                                          Hệ điều hành n bits
                              RAM tối đa
                                2n byte

                             Code     data   stack




            Con trỏ chỉ là
           một biến kiểu
           int lưu địa chỉ                               Byte 0
           của biến khác
                             Process                 Hệ điều
                             program                 hành nạp
                               code                  Process
                                                     lên RAM
                               data
   *.exe                                             để thực thi
                                                     quản lý theo
                              stack
                                                     địa chỉ
                                                                                3
Con trỏ cơ bản

1    Khai báo và cách sử dụng


2    Các cách truyền đối số cho hàm


3    Con trỏ và mảng một chiều


4    Con trỏ và cấu trúc




                                      4
Khai báo con trỏ và cách sử dụng
• Khai báo:
    Giống như mọi biến khác, biến con trỏ muốn sử dụng cũng
   cần phải được khai báo
     <kiểu dữ liệu> *<tên biến con trỏ>;


 Ví
 dụ:
       int a = 5;
       int *ptr;
       ptr = &a;                a                     ptr
                        Tên : a               Tên : ptr
                        Giá tri mà biến lưu   Giá trị mà biến lưu
                       trữ : 5                 trữ : 1025
                        Địa chỉ lưu trong      Địa chỉ lưu trong
                       bộ nhớ: 1025(giả        bộ nhớ: 5000(giả
                       định)                   định)

                                                                      5
Khai báo con trỏ và cách sử dụng
• Sử dụng từ khóa typedef

  typedef <kiểu dữ liệu> *<tên kiểu con trỏ>;
  <tên kiểu con trỏ> <tên biến con trỏ>;


• Ví dụ:
  typedef int *pInt;
  int *p1;
  pInt p2, p3;

Chý ý:
   • Giảm bối rối khi mới tiếp xúc với con trỏ.
   • Nhưng dễ nhầm lẫn với biến thường.
                                                  6
Khai báo con trỏ và cách sử dụng
• Con trỏ NULL
  – Con trỏ NULL là con trỏ không trỏ vào đâu cả.
  – Khác với con trỏ chưa được khởi tạo.
 int   n;
 int   *p1 = &n;
 int   *p2;       // Trỏ đến vùng nhớ kiểu int một cách ngẫu
 int   *p3 = NULL;nhiên

               p2
                                    NULL
  Chú ý:
        *p1 và n đều chỉ nội dung của biến n.
        p1 và &n đều chỉ địa chỉ của biến n.
                                                               7
Cách truyền đối số cho hàm

• Truyền địa chỉ (con trỏ) cho hàm
    #include <stdio.h>

    void hoanvi(int *x, int *y);

    void main()
    {
           int a = 3; b = 6;
           hoanvi(&a, &b);
           printf(“a = %d, b = %d”, a, b);
    }
    void hoanvi(int *x, int *y)
    {
           int t = *x; *x = *y; *y = t;
    }


                                             8
Con trỏ và mảng một chiều

• Mảng một chiều
     int Array[3];

  – Tên mảng Array là một hằng con trỏ
     không thể thay đổi giá trị của hằng này.
  – Giá trị của Array là địa chỉ phần tử đầu tiên của
    mảng
    Array == &Array[0]
     0A 0B 0C 0D 0E   0F   10 11 12 13 14 15 16 17

 …                                                   …

       Array                                             9
Con trỏ và mảng một chiều
• Con trỏ đến mảng một chiều
  int Array[3], *pArray;

  pArray = Array;             // Cách 1
  pArray = &Array[0];         // Cách 2
                           18 19 1A 1B 1C 1D 1E   1F

                      …      0B 00 00 00               …
                                 pArray

     0A 0B 0C 0D 0E   0F   10 11 12 13 14 15 16 17

 …                                                     …

       Array
                                                           10
Con trỏ và mảng một chiều
 Các phép toán số học trên con trỏ
• Phép cộng (tăng)
    + n  + n * sizeof(<kiểu dữ liệu>)
    Có thể sử dụng toán tử gộp += hoặc ++
        p = Array
                            +2
               +1

     0A 0B 0C 0D 0E   0F   10 11 12 13 14 15 16 17

 …                                                   …

        int Array[3]                                     11
Con trỏ và mảng một chiều
• Phép trừ (giảm)
   + n  + n * sizeof(<kiểu dữ liệu>)
   Có thể sử dụng toán tử gộp -= hoặc --
                                    p = &Array[2]
             –2

                             –1
     0A 0B 0C 0D 0E   0F   10 11 12 13 14 15 16 17

 …                                                   …

     int Array[3]                                        12
Con trỏ và mảng một chiều
// Nhập mảng                     // Xuất mảng
void main()                      void main()
{                                {
   int a[10], n = 10, *pa;          int a[10], n = 10, *pa;
   pa = a; // hoặc pa = &a[0];      pa = a; // hoặc pa = &a[0];

  for (int i = 0; i<n; i++)        for (int i = 0; i<n; i++)
       scanf(“%d”, &a[i]);              printf(“%d”, a[i]);
       // scanf(“%d”, &pa[i]);     // printf(“%d”, pa[i]);
      // scanf(“%d”, a + i);       // printf(“%d”, *(a + i));
      // scanf(“%d”, pa + i);      // printf(“%d”, *(pa + i));
      // scanf(“%d”, a++);         // printf(“%d”, *(a++);
      // scanf(“%d”, pa++);        // printf(“%d”, *(pa++));
}                                }
 &a[i]  (a + i)                 a[i]  *(a + i)
   (pa + i)  &pa[i]               *(pa + i)  pa[i]




                                                            13
Con trỏ và mảng một chiều

 Đối số mảng truyền cho hàm
 void xuat(int _a[10], int n)
 {
        for (int i = 0; i<n; i++)
               printf(“%d”, *(_a++));   // OK
 }
 void main()
 {
        int a[10], n = 10;

       for (int i = 0; i<n; i++)
              printf(“%d”, *(a++));     // Lỗi
 }

  Đối số mảng truyền cho hàm không phải hằng con trỏ.
                                                    14
Con trỏ và mảng một chiều
• Các phép toán khác
  – Phép so sánh: So sánh địa chỉ giữa hai con trỏ
    (thứ tự ô nhớ)
      == !=
      > >=
      < <=
  – Không thể thực hiện các phép toán: * / %




                                                     15
Con trỏ và cấu trúc

Truy xuất bằng 2 cách
  <tên biến con trỏ cấu trúc>-><tên thành phần>
  (*<tên biến con trỏ cấu trúc>).<tên thành phần>

Ví dụ
      typedef struct
      {
            int tu, mau;
      } PHANSO;
      PHANSO ps1, *ps2 = &ps1; // ps2 là con trỏ

      ps1.tu = 1; ps1.mau = 2;
      ps2->tu = 1; ps2->mau = 2;
       (*ps2).tu = 1; (*ps2).mau = 2;
                                                    16
Bài tập con trỏ cơ bản
Bài 1: Cho đoạn chương trình sau:
        float pay;
        float *ptr_pay;
        pay=2313.54;
        ptr_pay = &pay;

       Hãy cho biết giá trị của:
      a. pay
      b. *ptr_pay
      c. *pay
      d. &pay
                                     17
Bài tập con trỏ cơ bản
• Bài 2: Tìm lỗi
     #include <stdio.h>
     #include <conio.h>

     void main()
     {
           int *x, y = 2;

           *x = y;          Con trỏ x chưa được khởi
           *x += y++;       tạo

           printf("%d %d", *x, y);
           getch();
     }

                                                       18
Bài tập con trỏ cơ bản

• Bài tập 3: Cho biết giá trị xuất ra
   #include <stdio.h>
   #include <conio.h>          Output: ???
   void main()
   {
         int x=25;
         int *ptr=&x;
         int **temp=&ptr;
         printf(“%d %d %d”,x,*ptr,**temp);
   }
Bài tập con trỏ cơ bản
• Bài 4: Cho đoạn chương trình:
 #include <stdio.h>           Output: ???
 #include <conio.h>
  void main()
  {
     int *ptr=( int *)1000;
     ptr=ptr+1;
     printf(" %u",ptr);
 }
Bài tập con trỏ cơ bản
• Bài 5: Cho đoạn chương trình:
  #include <stdio.h>        Output: ???
  #include <conio.h>
     void main()
     {
          double *p=( double *)1000;
          p=p+3;
          printf(" %u",p);
     }
Bài tập con trỏ cơ bản
• Bài 6: Cho đoạn chương trình:
 #include <stdio.h>
 #include <conio.h>               Output: ???
 void calc(int* a, int b)
 {
    *a = b;
    *a += b++;
 }
 int main()
 {
    int x=5,y=6;
    calc (&x,y);
    printf(“%d %d”, x, y);
    return 0;
 }
Con trỏ nâng cao

1    Cấp phát động


2    Mảng con trỏ


3    Mảng động hai chiều


4    Con trỏ hàm




                           23
Cấp phát động
Để cấp phất động chúng ta sử dụng thư viện <stdlib.h>
   Cấp phát một khối nhớ size bytes trả về con trỏ void trỏ đến
  đầu khối nhớ đó và trả về NULL nếu thất bại.

   void *malloc( size );
                                           Số byte cần cấp phát



   Cấp phát một khối nhớ num*size bytes trả về con trỏ void trỏ
  đến đầu khối nhớ đó và trả về NULL nếu thất bại.
                                 Kích thước một khối nhớ

    void *calloc( num, size );
                                 Số lượng khối nhớ cần cấp phát
                                                                  24
Cấp phát động
Ví dụ:
  Dùng con trỏ dVar để quản lý khối nhớ động kiểu double vừa được malloc cấp phát.
     double *dVar;
     dVar = (double*) malloc ( sizeof(double) );
 Tương tự với calloc
     double *dVar;
     dVar = (double*) calloc ( 1 , sizeof(double) );
   Để có được một mảng động với n phần tử trong bộ nhớ ta làm như sau:
     double *dVar;
     dVar = (double*) malloc ( n*sizeof(double) );


     double *dVar;
     dVar = (double*) calloc ( n , sizeof(double) );
                                                                            25
Mảng con trỏ
Đặt vấn đề
   • Khi cần lưu trữ những dãy dữ liệu lớn kích thước không bằng nhau ví dụ
   như một dãy tên sinh viên chẳng hạn nếu ta dùng mảng hai chiều để lưu
   trữ sẽ dẫn đến lãng phí do kích thước mỗi tên phải bằng nhau.
 Giải quyết vấn đề
   •Ta dùng một cách lưu trữ mới đó là mảng con trỏ. Với bài toán lưu trữ và xử lý dãy
   tên sinh viên ta khai báo mảng sau.

    • Khai báo :                                     •Nhập
        #define max 100;                               for( int i=0; i<max ; i++)
        char *pChar[max];                              {
                                                         printf(“Name*%d+= “,i);
            •Xuất                                        scanf(“%s”,pChar[i]);
               for( int i=0; i<max ; i++)              }
                 {
                   printf(“Name*%d+=%s“,pChar[i]);
                 }
                                                                                    26
Mảng động hai chiều
Khai báo và cấp phát
  • Khai báo:
    DataType **Matrix;
    int      Rows, Columns;

  • Cấp phát Rows dòng cho ma trận thực chất là mảng
  một chiều gồm Rows con trỏ kiểu DataType.
    Matrix = (DataType**) calloc(Rows , sizeof(DataType*));


  • Cấp phát cho mỗi dòng Columns phần tử
    for (int i=0 ; i<Rows; i++)
                Matrix[i]=(DataType *) malloc(Columns*sizeof(DataType));

                                                                           27
Mảng động hai chiều
 Sử dụng:
typedef int DataType;                        typedef int DataType;
void Nhap(DataType **M,int r,int c)          void Xuat(DataType **M,int r,int c)
{                                            {
  int i,j;                                     int i,j;
  for ( i=0 ; i<r ; i++)                       for ( i=0 ; i<r ; i++)
      for ( j=0 ; j<c ; j++)                       for ( j=0 ; j<c ; j++)
     {                                            {
           printf("Nhap M[%d][%d]= ",i,j);
           scanf("%d",&M[i][j]);                      printf(“M*%d+*%d+ = %d ", i,j,M[i][j]);
            // Hoặc *(M+i)+j                          // Hoặc *(*(M+i)+j)
     }                                            }
}                                            }



                                                                                      28
Mảng động hai chiều
 Hủy:
     • Giải phóng từng dòng một
         for ( i=0 ; i<Rows ; i++)
              free (Matrix[i]);

     • Giải phóng Matrix
         free (Matrix);




                                     29
Con trỏ hàm
Khái niệm
  – Hàm cũng đuợc lưu trữ trong bộ nhớ, tức là cũng
    có địa chỉ.
  – Con trỏ hàm là con trỏ trỏ đến vùng nhớ chứa
    hàm và có thể gọi hàm thông qua con trỏ đó.


       0A 0B 0C 0D 0E   0F    10 11 12 13 14 15 16 17

   …     11 00 00 00                                    …

          p                  int Cong(int, int)
                                                            30
Con trỏ hàm
Khai báo tường minh
  <kiểu trả về> (* <tên biến con trỏ>)(ds tham số);

 Khai báo không tường minh – bằng typedef
  typedef <kiểu trả về> (* <tên con trỏ hàm>)(ds tham số);
  <tên con trỏ hàm> <tên biến con trỏ>;

Ví dụ
  int (*pt1)(int, int);     // Tường minh

  typedef int (*PhepToan)(int, int);

  PhepToan pt2, pt3;        // Không tường minh
                                                        31
Con trỏ hàm

Gán giá trị cho con trỏ hàm
   <biến con trỏ hàm> = <tên hàm>; // Dạng ngắn gọn
   <biến con trỏ hàm> = &<tên hàm>; // Dạng sử dụng địa chỉ

  Hàm được gán phải cùng dạng (ds tham số)
Ví dụ
   int Cong( int x, int y);                // Hàm
   int Tru( int x, int y);                 // Hàm
   int (*tinhtoan)(int x, int y);          // Con trỏ hàm

   tinhtoan = Cong;    // Dạng ngắn gọn
   tinhtoan = &Tru;    // Dạng sử dụng địa chỉ
   tinhtoan = NULL;    // Không trỏ đến đâu cả

                                                        32
Thu hoạch
  Câu nói nào sau đây là đúng !
 A. “ Dùng con trỏ để giải bài A”
 B. “ Giải bài tập B sử dụng con trỏ”
 C. “ Giải bài tập C bằng con trỏ ”



                                        33
Tài liệu tham khảo
• Kĩ thuật lập trình – Đặng Bình Phương –
  Khoa Công nghệ thông tin - ĐH KHTN.
• Everything you need to know about pointers
  in C- Version 1.3 - Copyright 2005–2010 Peter
  Hosey.
• Understanding Pointers In C By Yashwant
  Kanetkar.


                                                  34

Weitere ähnliche Inhalte

Was ist angesagt?

Session 4
Session 4Session 4
Session 4pnanhvn
 
Nmlt C03 Cac Kieu Du Lieu Co So
Nmlt C03 Cac Kieu Du Lieu Co SoNmlt C03 Cac Kieu Du Lieu Co So
Nmlt C03 Cac Kieu Du Lieu Co SoCuong
 
chuỗi ký tự c++
chuỗi ký tự c++chuỗi ký tự c++
chuỗi ký tự c++ptquang160492
 
Thu vien lap trinh c++
Thu vien lap trinh c++Thu vien lap trinh c++
Thu vien lap trinh c++ptquang160492
 
Lap trinh huong_doi_tuong_cpp_dhct_lesson08
Lap trinh huong_doi_tuong_cpp_dhct_lesson08Lap trinh huong_doi_tuong_cpp_dhct_lesson08
Lap trinh huong_doi_tuong_cpp_dhct_lesson08xcode_esvn
 
Phần 7: Mảng một chiều
Phần 7: Mảng một chiềuPhần 7: Mảng một chiều
Phần 7: Mảng một chiềuHuy Rùa
 
Hàm và Chuỗi
Hàm và ChuỗiHàm và Chuỗi
Hàm và Chuỗipnanhvn
 

Was ist angesagt? (13)

String c++
String c++String c++
String c++
 
Nmlt c09 chuoi_kytu
Nmlt c09 chuoi_kytuNmlt c09 chuoi_kytu
Nmlt c09 chuoi_kytu
 
Session 4
Session 4Session 4
Session 4
 
Nmlt C03 Cac Kieu Du Lieu Co So
Nmlt C03 Cac Kieu Du Lieu Co SoNmlt C03 Cac Kieu Du Lieu Co So
Nmlt C03 Cac Kieu Du Lieu Co So
 
chuỗi ký tự c++
chuỗi ký tự c++chuỗi ký tự c++
chuỗi ký tự c++
 
Thu vien lap trinh c++
Thu vien lap trinh c++Thu vien lap trinh c++
Thu vien lap trinh c++
 
Pointer
PointerPointer
Pointer
 
Pointer vn
Pointer vnPointer vn
Pointer vn
 
Lap trinh huong_doi_tuong_cpp_dhct_lesson08
Lap trinh huong_doi_tuong_cpp_dhct_lesson08Lap trinh huong_doi_tuong_cpp_dhct_lesson08
Lap trinh huong_doi_tuong_cpp_dhct_lesson08
 
Phần 7: Mảng một chiều
Phần 7: Mảng một chiềuPhần 7: Mảng một chiều
Phần 7: Mảng một chiều
 
Hàm và Chuỗi
Hàm và ChuỗiHàm và Chuỗi
Hàm và Chuỗi
 
Ctdl lab01
Ctdl lab01Ctdl lab01
Ctdl lab01
 
Chapter04 array
Chapter04 arrayChapter04 array
Chapter04 array
 

Andere mochten auch

Historieta o comics
Historieta o comicsHistorieta o comics
Historieta o comicsgiovavilela
 
electronic document management
electronic document managementelectronic document management
electronic document managementnim_nenuphar
 
Thorndike2 measurement and numbers
Thorndike2 measurement and numbersThorndike2 measurement and numbers
Thorndike2 measurement and numbersRoi Xcel
 
Article iv of cmo 38
Article iv of cmo 38Article iv of cmo 38
Article iv of cmo 38Roi Xcel
 
Book 4 health, safety and social welfare benefits
Book 4 health, safety and social welfare benefitsBook 4 health, safety and social welfare benefits
Book 4 health, safety and social welfare benefitsRoi Xcel
 
I/O chapter 3
I/O chapter 3I/O chapter 3
I/O chapter 3Roi Xcel
 
Pap code of ethics assessment
Pap code of ethics assessmentPap code of ethics assessment
Pap code of ethics assessmentRoi Xcel
 
Book 3 conditions of employment
Book 3 conditions of employmentBook 3 conditions of employment
Book 3 conditions of employmentRoi Xcel
 
Reliability
ReliabilityReliability
ReliabilityRoi Xcel
 
Chapter 1 history of testing
Chapter 1 history of testingChapter 1 history of testing
Chapter 1 history of testingRoi Xcel
 
Contracting and subcontracting
Contracting and subcontractingContracting and subcontracting
Contracting and subcontractingRoi Xcel
 
Procedural due process
Procedural due processProcedural due process
Procedural due processRoi Xcel
 
Human development
Human developmentHuman development
Human developmentRoi Xcel
 

Andere mochten auch (17)

Amalan bulan rajab
Amalan bulan rajabAmalan bulan rajab
Amalan bulan rajab
 
Historieta o comics
Historieta o comicsHistorieta o comics
Historieta o comics
 
electronic document management
electronic document managementelectronic document management
electronic document management
 
Thorndike2 measurement and numbers
Thorndike2 measurement and numbersThorndike2 measurement and numbers
Thorndike2 measurement and numbers
 
Membuat pcb
Membuat pcbMembuat pcb
Membuat pcb
 
Prosedur kkm
Prosedur kkmProsedur kkm
Prosedur kkm
 
Article iv of cmo 38
Article iv of cmo 38Article iv of cmo 38
Article iv of cmo 38
 
Book 4 health, safety and social welfare benefits
Book 4 health, safety and social welfare benefitsBook 4 health, safety and social welfare benefits
Book 4 health, safety and social welfare benefits
 
I/O chapter 3
I/O chapter 3I/O chapter 3
I/O chapter 3
 
Pap code of ethics assessment
Pap code of ethics assessmentPap code of ethics assessment
Pap code of ethics assessment
 
Book 3 conditions of employment
Book 3 conditions of employmentBook 3 conditions of employment
Book 3 conditions of employment
 
16 pf
16 pf16 pf
16 pf
 
Reliability
ReliabilityReliability
Reliability
 
Chapter 1 history of testing
Chapter 1 history of testingChapter 1 history of testing
Chapter 1 history of testing
 
Contracting and subcontracting
Contracting and subcontractingContracting and subcontracting
Contracting and subcontracting
 
Procedural due process
Procedural due processProcedural due process
Procedural due process
 
Human development
Human developmentHuman development
Human development
 

Ähnlich wie Slide pointer sepro

Lec3. Ham.pdf
Lec3. Ham.pdfLec3. Ham.pdf
Lec3. Ham.pdfKinHongnh
 
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programmingLập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programmingbeatmaking
 
Bai giangtrenlop
Bai giangtrenlopBai giangtrenlop
Bai giangtrenlopHồ Lợi
 
LAP TRINH C - SESSION 2
LAP TRINH C - SESSION 2LAP TRINH C - SESSION 2
LAP TRINH C - SESSION 2pnanhvn
 
Ngon ngu c theo chuan ansi
Ngon ngu c theo chuan ansiNgon ngu c theo chuan ansi
Ngon ngu c theo chuan ansiHuynh MVT
 
Group 14_pointer_beta2.pptx
Group 14_pointer_beta2.pptxGroup 14_pointer_beta2.pptx
Group 14_pointer_beta2.pptxChuHaBnh
 
Lap trinh huong_doi_tuong_cpp_dhct_lesson05
Lap trinh huong_doi_tuong_cpp_dhct_lesson05Lap trinh huong_doi_tuong_cpp_dhct_lesson05
Lap trinh huong_doi_tuong_cpp_dhct_lesson05xcode_esvn
 
Tóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cTóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cHồ Lợi
 
Thdc3 Lap Trinh C
Thdc3 Lap Trinh CThdc3 Lap Trinh C
Thdc3 Lap Trinh Cquyloc
 
C cho 8051
C cho 8051C cho 8051
C cho 8051Nhan Bui
 

Ähnlich wie Slide pointer sepro (20)

Session 13
Session 13Session 13
Session 13
 
Nmlt c11 con_trocoban
Nmlt c11 con_trocobanNmlt c11 con_trocoban
Nmlt c11 con_trocoban
 
344444
344444344444
344444
 
Lec3. Ham.pdf
Lec3. Ham.pdfLec3. Ham.pdf
Lec3. Ham.pdf
 
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programmingLập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
 
Bai giangtrenlop
Bai giangtrenlopBai giangtrenlop
Bai giangtrenlop
 
LAP TRINH C - SESSION 2
LAP TRINH C - SESSION 2LAP TRINH C - SESSION 2
LAP TRINH C - SESSION 2
 
Ngon ngu c theo chuan ansi
Ngon ngu c theo chuan ansiNgon ngu c theo chuan ansi
Ngon ngu c theo chuan ansi
 
Session 11
Session 11Session 11
Session 11
 
Session 11
Session 11Session 11
Session 11
 
Group 14_pointer_beta2.pptx
Group 14_pointer_beta2.pptxGroup 14_pointer_beta2.pptx
Group 14_pointer_beta2.pptx
 
Lesson05
Lesson05Lesson05
Lesson05
 
Lap trinh huong_doi_tuong_cpp_dhct_lesson05
Lap trinh huong_doi_tuong_cpp_dhct_lesson05Lap trinh huong_doi_tuong_cpp_dhct_lesson05
Lap trinh huong_doi_tuong_cpp_dhct_lesson05
 
C đến C++ phần 1
C đến C++ phần 1C đến C++ phần 1
C đến C++ phần 1
 
Lesson05
Lesson05Lesson05
Lesson05
 
Tóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cTóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của c
 
Thdc3 Lap Trinh C
Thdc3 Lap Trinh CThdc3 Lap Trinh C
Thdc3 Lap Trinh C
 
Lect05 array
Lect05 arrayLect05 array
Lect05 array
 
Basic C programming
Basic C programmingBasic C programming
Basic C programming
 
C cho 8051
C cho 8051C cho 8051
C cho 8051
 

Slide pointer sepro

  • 1. ĐẠI HỌC CÔNG NGHỆ THÔNG TIN - ĐHQG Tp HCM – SE05 CON TRỎ TRONG NGÔN NGỮ C/C++ SE-PRO GROUP 1
  • 2. NỘI DUNG:  DẪN NHẬP  CON TRỎ CƠ BẢN  CON TRỎ NÂNG CAO TÀI LIỆU THAM KHẢO 2
  • 3. DẪN NHẬP Byte 2n Memory (RAM) Win n bit thì Hệ điều hành n bits RAM tối đa 2n byte Code data stack Con trỏ chỉ là một biến kiểu int lưu địa chỉ Byte 0 của biến khác Process Hệ điều program hành nạp code Process lên RAM data *.exe để thực thi quản lý theo stack địa chỉ 3
  • 4. Con trỏ cơ bản 1 Khai báo và cách sử dụng 2 Các cách truyền đối số cho hàm 3 Con trỏ và mảng một chiều 4 Con trỏ và cấu trúc 4
  • 5. Khai báo con trỏ và cách sử dụng • Khai báo:  Giống như mọi biến khác, biến con trỏ muốn sử dụng cũng cần phải được khai báo <kiểu dữ liệu> *<tên biến con trỏ>; Ví dụ: int a = 5; int *ptr; ptr = &a; a ptr  Tên : a Tên : ptr  Giá tri mà biến lưu Giá trị mà biến lưu trữ : 5 trữ : 1025  Địa chỉ lưu trong  Địa chỉ lưu trong bộ nhớ: 1025(giả bộ nhớ: 5000(giả định) định) 5
  • 6. Khai báo con trỏ và cách sử dụng • Sử dụng từ khóa typedef typedef <kiểu dữ liệu> *<tên kiểu con trỏ>; <tên kiểu con trỏ> <tên biến con trỏ>; • Ví dụ: typedef int *pInt; int *p1; pInt p2, p3; Chý ý: • Giảm bối rối khi mới tiếp xúc với con trỏ. • Nhưng dễ nhầm lẫn với biến thường. 6
  • 7. Khai báo con trỏ và cách sử dụng • Con trỏ NULL – Con trỏ NULL là con trỏ không trỏ vào đâu cả. – Khác với con trỏ chưa được khởi tạo. int n; int *p1 = &n; int *p2; // Trỏ đến vùng nhớ kiểu int một cách ngẫu int *p3 = NULL;nhiên p2 NULL Chú ý:  *p1 và n đều chỉ nội dung của biến n.  p1 và &n đều chỉ địa chỉ của biến n. 7
  • 8. Cách truyền đối số cho hàm • Truyền địa chỉ (con trỏ) cho hàm #include <stdio.h> void hoanvi(int *x, int *y); void main() { int a = 3; b = 6; hoanvi(&a, &b); printf(“a = %d, b = %d”, a, b); } void hoanvi(int *x, int *y) { int t = *x; *x = *y; *y = t; } 8
  • 9. Con trỏ và mảng một chiều • Mảng một chiều int Array[3]; – Tên mảng Array là một hằng con trỏ  không thể thay đổi giá trị của hằng này. – Giá trị của Array là địa chỉ phần tử đầu tiên của mảng Array == &Array[0] 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 … … Array 9
  • 10. Con trỏ và mảng một chiều • Con trỏ đến mảng một chiều int Array[3], *pArray; pArray = Array; // Cách 1 pArray = &Array[0]; // Cách 2 18 19 1A 1B 1C 1D 1E 1F … 0B 00 00 00 … pArray 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 … … Array 10
  • 11. Con trỏ và mảng một chiều  Các phép toán số học trên con trỏ • Phép cộng (tăng)  + n  + n * sizeof(<kiểu dữ liệu>)  Có thể sử dụng toán tử gộp += hoặc ++ p = Array +2 +1 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 … … int Array[3] 11
  • 12. Con trỏ và mảng một chiều • Phép trừ (giảm)  + n  + n * sizeof(<kiểu dữ liệu>)  Có thể sử dụng toán tử gộp -= hoặc -- p = &Array[2] –2 –1 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 … … int Array[3] 12
  • 13. Con trỏ và mảng một chiều // Nhập mảng // Xuất mảng void main() void main() { { int a[10], n = 10, *pa; int a[10], n = 10, *pa; pa = a; // hoặc pa = &a[0]; pa = a; // hoặc pa = &a[0]; for (int i = 0; i<n; i++) for (int i = 0; i<n; i++) scanf(“%d”, &a[i]); printf(“%d”, a[i]); // scanf(“%d”, &pa[i]); // printf(“%d”, pa[i]); // scanf(“%d”, a + i); // printf(“%d”, *(a + i)); // scanf(“%d”, pa + i); // printf(“%d”, *(pa + i)); // scanf(“%d”, a++); // printf(“%d”, *(a++); // scanf(“%d”, pa++); // printf(“%d”, *(pa++)); } }  &a[i]  (a + i)  a[i]  *(a + i)  (pa + i)  &pa[i]  *(pa + i)  pa[i] 13
  • 14. Con trỏ và mảng một chiều  Đối số mảng truyền cho hàm void xuat(int _a[10], int n) { for (int i = 0; i<n; i++) printf(“%d”, *(_a++)); // OK } void main() { int a[10], n = 10; for (int i = 0; i<n; i++) printf(“%d”, *(a++)); // Lỗi }  Đối số mảng truyền cho hàm không phải hằng con trỏ. 14
  • 15. Con trỏ và mảng một chiều • Các phép toán khác – Phép so sánh: So sánh địa chỉ giữa hai con trỏ (thứ tự ô nhớ)  == !=  > >=  < <= – Không thể thực hiện các phép toán: * / % 15
  • 16. Con trỏ và cấu trúc Truy xuất bằng 2 cách <tên biến con trỏ cấu trúc>-><tên thành phần> (*<tên biến con trỏ cấu trúc>).<tên thành phần> Ví dụ typedef struct { int tu, mau; } PHANSO; PHANSO ps1, *ps2 = &ps1; // ps2 là con trỏ ps1.tu = 1; ps1.mau = 2; ps2->tu = 1; ps2->mau = 2;  (*ps2).tu = 1; (*ps2).mau = 2; 16
  • 17. Bài tập con trỏ cơ bản Bài 1: Cho đoạn chương trình sau: float pay; float *ptr_pay; pay=2313.54; ptr_pay = &pay;  Hãy cho biết giá trị của: a. pay b. *ptr_pay c. *pay d. &pay 17
  • 18. Bài tập con trỏ cơ bản • Bài 2: Tìm lỗi #include <stdio.h> #include <conio.h> void main() { int *x, y = 2; *x = y; Con trỏ x chưa được khởi *x += y++; tạo printf("%d %d", *x, y); getch(); } 18
  • 19. Bài tập con trỏ cơ bản • Bài tập 3: Cho biết giá trị xuất ra #include <stdio.h> #include <conio.h> Output: ??? void main() { int x=25; int *ptr=&x; int **temp=&ptr; printf(“%d %d %d”,x,*ptr,**temp); }
  • 20. Bài tập con trỏ cơ bản • Bài 4: Cho đoạn chương trình: #include <stdio.h> Output: ??? #include <conio.h> void main() { int *ptr=( int *)1000; ptr=ptr+1; printf(" %u",ptr); }
  • 21. Bài tập con trỏ cơ bản • Bài 5: Cho đoạn chương trình: #include <stdio.h> Output: ??? #include <conio.h> void main() { double *p=( double *)1000; p=p+3; printf(" %u",p); }
  • 22. Bài tập con trỏ cơ bản • Bài 6: Cho đoạn chương trình: #include <stdio.h> #include <conio.h> Output: ??? void calc(int* a, int b) { *a = b; *a += b++; } int main() { int x=5,y=6; calc (&x,y); printf(“%d %d”, x, y); return 0; }
  • 23. Con trỏ nâng cao 1 Cấp phát động 2 Mảng con trỏ 3 Mảng động hai chiều 4 Con trỏ hàm 23
  • 24. Cấp phát động Để cấp phất động chúng ta sử dụng thư viện <stdlib.h>  Cấp phát một khối nhớ size bytes trả về con trỏ void trỏ đến đầu khối nhớ đó và trả về NULL nếu thất bại. void *malloc( size ); Số byte cần cấp phát  Cấp phát một khối nhớ num*size bytes trả về con trỏ void trỏ đến đầu khối nhớ đó và trả về NULL nếu thất bại. Kích thước một khối nhớ void *calloc( num, size ); Số lượng khối nhớ cần cấp phát 24
  • 25. Cấp phát động Ví dụ:  Dùng con trỏ dVar để quản lý khối nhớ động kiểu double vừa được malloc cấp phát. double *dVar; dVar = (double*) malloc ( sizeof(double) ); Tương tự với calloc double *dVar; dVar = (double*) calloc ( 1 , sizeof(double) );  Để có được một mảng động với n phần tử trong bộ nhớ ta làm như sau: double *dVar; dVar = (double*) malloc ( n*sizeof(double) ); double *dVar; dVar = (double*) calloc ( n , sizeof(double) ); 25
  • 26. Mảng con trỏ Đặt vấn đề • Khi cần lưu trữ những dãy dữ liệu lớn kích thước không bằng nhau ví dụ như một dãy tên sinh viên chẳng hạn nếu ta dùng mảng hai chiều để lưu trữ sẽ dẫn đến lãng phí do kích thước mỗi tên phải bằng nhau.  Giải quyết vấn đề •Ta dùng một cách lưu trữ mới đó là mảng con trỏ. Với bài toán lưu trữ và xử lý dãy tên sinh viên ta khai báo mảng sau. • Khai báo : •Nhập #define max 100; for( int i=0; i<max ; i++) char *pChar[max]; { printf(“Name*%d+= “,i); •Xuất scanf(“%s”,pChar[i]); for( int i=0; i<max ; i++) } { printf(“Name*%d+=%s“,pChar[i]); } 26
  • 27. Mảng động hai chiều Khai báo và cấp phát • Khai báo: DataType **Matrix; int Rows, Columns; • Cấp phát Rows dòng cho ma trận thực chất là mảng một chiều gồm Rows con trỏ kiểu DataType. Matrix = (DataType**) calloc(Rows , sizeof(DataType*)); • Cấp phát cho mỗi dòng Columns phần tử for (int i=0 ; i<Rows; i++) Matrix[i]=(DataType *) malloc(Columns*sizeof(DataType)); 27
  • 28. Mảng động hai chiều Sử dụng: typedef int DataType; typedef int DataType; void Nhap(DataType **M,int r,int c) void Xuat(DataType **M,int r,int c) { { int i,j; int i,j; for ( i=0 ; i<r ; i++) for ( i=0 ; i<r ; i++) for ( j=0 ; j<c ; j++) for ( j=0 ; j<c ; j++) { { printf("Nhap M[%d][%d]= ",i,j); scanf("%d",&M[i][j]); printf(“M*%d+*%d+ = %d ", i,j,M[i][j]); // Hoặc *(M+i)+j // Hoặc *(*(M+i)+j) } } } } 28
  • 29. Mảng động hai chiều  Hủy: • Giải phóng từng dòng một for ( i=0 ; i<Rows ; i++) free (Matrix[i]); • Giải phóng Matrix free (Matrix); 29
  • 30. Con trỏ hàm Khái niệm – Hàm cũng đuợc lưu trữ trong bộ nhớ, tức là cũng có địa chỉ. – Con trỏ hàm là con trỏ trỏ đến vùng nhớ chứa hàm và có thể gọi hàm thông qua con trỏ đó. 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 … 11 00 00 00 … p int Cong(int, int) 30
  • 31. Con trỏ hàm Khai báo tường minh <kiểu trả về> (* <tên biến con trỏ>)(ds tham số);  Khai báo không tường minh – bằng typedef typedef <kiểu trả về> (* <tên con trỏ hàm>)(ds tham số); <tên con trỏ hàm> <tên biến con trỏ>; Ví dụ int (*pt1)(int, int); // Tường minh typedef int (*PhepToan)(int, int); PhepToan pt2, pt3; // Không tường minh 31
  • 32. Con trỏ hàm Gán giá trị cho con trỏ hàm <biến con trỏ hàm> = <tên hàm>; // Dạng ngắn gọn <biến con trỏ hàm> = &<tên hàm>; // Dạng sử dụng địa chỉ Hàm được gán phải cùng dạng (ds tham số) Ví dụ int Cong( int x, int y); // Hàm int Tru( int x, int y); // Hàm int (*tinhtoan)(int x, int y); // Con trỏ hàm tinhtoan = Cong; // Dạng ngắn gọn tinhtoan = &Tru; // Dạng sử dụng địa chỉ tinhtoan = NULL; // Không trỏ đến đâu cả 32
  • 33. Thu hoạch Câu nói nào sau đây là đúng ! A. “ Dùng con trỏ để giải bài A” B. “ Giải bài tập B sử dụng con trỏ” C. “ Giải bài tập C bằng con trỏ ” 33
  • 34. Tài liệu tham khảo • Kĩ thuật lập trình – Đặng Bình Phương – Khoa Công nghệ thông tin - ĐH KHTN. • Everything you need to know about pointers in C- Version 1.3 - Copyright 2005–2010 Peter Hosey. • Understanding Pointers In C By Yashwant Kanetkar. 34