Slide bài giảng Lập trình C++ - Lương Trần Hy Hiến - Con trỏ
Nội dung
Tổchức của chương trình
Địa chỉ
Biến con trỏ
Các thao tác trên biến con trỏ
Biến tĩnh và biến động
Cấp phát và hủy biến động
Tóm tắt nội dung Slide bài giảng Lập trình C++ - Lương Trần Hy Hiến - Con trỏ, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
HIENLTH, C++ - 2010 Nội dung Tổ chức của chương trình Địa chỉ Biến con trỏ HIENLTH, C++ - 2010 Các thao tác trên biến con trỏ Biến tĩnh và biến động Cấp phát và hủy biến động 2 Tổ chức của chương trình Một chương trình được chia ra thành nhiều phân đoạn (segment). Mỗi segment có thể xem như là một mảng một chiều. HIENLTH, C++ - 2010 Mỗi segment lưu một loại dữ liệu nhất định. Data Segment: lưu các biến toàn cục Stack Segment: lưu các biến cục bộ của các hàm và các thông tin khác Heap Segment: lưu các biến động Code Segment: lưu các chỉ thị đoạn mã của chương trình 3 Địa chỉ Một ô nhớ bất kỳ (một biến bất kỳ) trong chương trình có một địa chỉ duy nhất. Mỗi địa chỉ gồm có hai thành phần: Tên segment l u biến HIENLTH, C++ - 2010 ư Vị trí của biến trong segment Địa chỉ thường được ký hiệu là segment:offset Segment có thể là Data, Heap, Code, Stack Offset là vị trí của biến trong segment tương ứng 4 Ví dụ int a; void main() { 16 12 16 12 HIENLTH, C++ - 2010 5 int b; double c; … } 8 4 0 a Stack Data 8 c 4 0 b Con trỏ – Một số lý do nên sử dụng Con trỏ là kiểu dữ liệu lưu trữ địa chỉ của các vùng dữ liệu trong bộ nhớ máy tính Kiểu con trỏ cho phép: Truyền tham số kiểu địa chỉ HIENLTH, C++ - 2010 Biểu diễn các kiểu, cấu trúc dữ liệu động Lưu trữ dữ liệu trong vùng nhớ heap Biến con trỏ Là biến dùng để lưu giá trị địa chỉ Cú pháp khai báo một biến con trỏ Kiểu* tên-biến; Ý nghĩa: khai báo một biến con trỏ dùng để lưu địa chỉ của HIENLTH, C++ - 2010 các biến thuộc kiểu đã chỉ ra. Biến con trỏ có kích thước 4 bytes (hệ điều hành 32 bit) Ví dụ: int* pint; // khai báo một biến con trỏ dùng để lưu địa chỉ của các biến thuộc kiểu int. double* pd; // khai báo một biến con trỏ dùng để lưu địa chỉ của các biến thuộc kiểu double. 7 Con trỏ – Khai báo trong C++ int *pi; long int *p; fl t* f HIENLTH, C++ - 2010 8 oa p ; char c, d, *pc; /* c và d kiểu char pc là con trỏ đến char */ double* pd, e, f; /* pd là con trỏ đến double e and f are double */ char *start, *end; Các thao tác trên con trỏ Phép lấy địa chỉ: Kí hiệu: & Cú pháp: &tên-biến Ý nghĩa: lấy địa chỉ của biến đi kèm. Biến được lấy địa HIENLTH, C++ - 2010 chỉ phải thuộc kiểu mà con trỏ có thể lưu địa chỉ. Ví dụ: int a = 5; int* pa = &a; // pa sẽ lưu địa chỉ của biến a int **pb = &pa;//pb lưu địa chỉ của con trỏ pa 9 Con trỏ - Toán tử “&” Địa chỉ của tất cả các biến trong chương trình đều đã được chỉ định từ khi khai báo. char g = 'z'; p c HIENLTH, C++ - 2010 10 0x91A2 0x1132 void main() { char c = 'a'; char *p; p = &c; p = &g; } 'a' 0x1132 p g 'z' 0x91A2 Con trỏ - Toán tử * Phép khử địa chỉ Kí hiệu: * Cú pháp: *tên-biến-con-trỏ Ý ngh a: truy xuất ến vùng nh có a chỉ ang c HIENLTH, C++ - 2010 ĩ đ ớ đị đ đượ lưu bởi biến con trỏ đi kèm Ví dụ: int a = 5; int* pa = &a; *pa = 6; cout << *pa; 11 Con trỏ - Toán tử * #include using namespace std; char g = 'z'; void main() a z 0x1132 p c 'a' 0x1132 HIENLTH, C++ - 2010 12 { char c = 'a'; char *p; p = &c; cout<<*p<<"\n"; p = &g; cout<<*p<<"\n"; } xuất giá trị do p đang quản lý 0x91A2 p g 'z' 0x91A2 Con trỏ - Truyền tham số địa chỉ #include using namespace std; void change(int *v); void main() HIENLTH, C++ - 2010 13 { int var = 5; change(&var); cout<<"main: var = “<<var<<endl; } void change(int *v) { (*v) *= 100; cout<<“change: *v = “<< (*v)<<endl; } Con trỏ - Truyền tham số địa chỉ void Swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } HIENLTH, C++ - 2010 void main() { int m = 5, n = 7; cout<<“m = “<<m<<“, n = “<<n<<endl; Swap(&m, &n); cout<<“m = “<<m<<“, n = “<<n<<endl; } 14 Con trỏ NULL Giá trị đặc biệt để chỉ rằng con trỏ không quản lý vùng nào. Giá trị này thường được dùng để chỉ một con trỏ không hợp lệ. #i l d i t HIENLTH, C++ - 2010 15 nc u e using namespace std; void main() { int i = 13; short *p = NULL; if (p == NULL) cout<<“Con trỏ không hợp lệ!\n"; else cout<<“Giá trị : “<<*p<<“\n"; } Con trỏ - Toán tử gán “=” Có sự khác biệt rất quan trọng khi thực hiện các phép gán: 0x15A0int i = 10, j = 14; int* p = &i; p i 10 0x15A0 14 HIENLTH, C++ - 2010 16 0x15A0 0x15A4 int *q = &j; *p = *q; int i = 10, j = 14; int *p = &i; int *q = &j; p = q; và: q j 0x15A4 14 p i 10 0x15A0q j 0x15A4 0x15A4 14 0x15A4 Luyện tập – Điền vào ô trống void main() { inti = 10, j = 14, k; int*p = &i; i 0x2100 j 0x2104 HIENLTH, C++ - 2010 17 int*q = &j; *p += 1; p = &k; *p = *q; p = q; *p = *q; } k 0x1208 p 0x120B q 0x1210 Con trỏ và mảng Tên mảng được coi như là một con trỏ trỏ tới phần tử đầu tiên của mảng. int A[6] = {2, 4, 6, 8, 10, 12}; HIENLTH, C++ - 2010 18 int *P; P = A; Con trỏ và Mảng Biến kiểu mảng là địa chỉ tĩnh của một vùng nhớ, được xác định khi khai báo, không thay đổi trong suốt chu kỳ sống. Biến con trỏ là địa chỉ động của một vùng nhớ, được xác HIENLTH, C++ - 2010 định qua phép gán địa chỉ khi chương trình thực thi. 19 #include using namespace std; void main() { int a[10] = {1, 3, 4, 2, 0}; int *p; p = a; //a = p: sai cout<<a<<a[0]<<p<<*p<<endl; } Ví dụ con trỏ và mảng Bắt đầu: HIENLTH, C++ - 2010 20 Thực hiện P = &A[2]; Bây giờ, P[0] là A[2], P[1] là A[3], … Con trỏ - Toán tử “+” với số nguyên 34 #include using namespace std; void main() { short a[10] = {1, 3, 5, 2, 0}; 1 5 a 0x15A0 HIENLTH, C++ - 2010 21 0x15A02 short *p = a; cout<<a<<a[0]<<p<<*p<<endl; p ++; cout<<a<<a[0]<<p<<*p<<endl; (*p) ++; cout<<a<<a[0]<<p<<*p<<endl; } 2 0 … p0x16B2 Con trỏ và mảng Giả sử con trỏ ptr trỏ tới phần tử a[i] nào đó của mảng a, thì: ptr + j chỉ đến phần tử thứ j sau a[i], tức a[i+j] ptr - j chỉ đến phần tử thứ j tr ớc a[i], tức a[i-j] HIENLTH, C++ - 2010 ư 22 Các phép toán trên con trỏ HIENLTH, C++ - 2010 23 Con trỏ - Luyện tập void main() { int a[10] = {2, 3, 5, 1, 4, 7, 0}; 2 2 3 1 1 9 1 3 HIENLTH, C++ - 2010 24 int *p = a; cout<< a[0] << *p <<endl; p ++; cout<< *p << p[2] <<endl; p ++; a[2] = 9; cout<< p[1] << *p; p -= 2; cout<< p[3] << p[1] <<endl; } Biến tĩnh và biến động Biến tĩnh Biến động Có tên Không có tên HIENLTH, C++ - 2010 Kích thước cố định Kích thước không cố định Được cấp phát tự động trong Data Segment hoặc Stack Segment Được cấp phát trong Heap Segment Phạm vi sử dụng từ lúc khai báo đến hết khối gần nhất chứa nó. Phạm vi sử dụng bắt đầu từ lúc được tạo ra và kết thúc khi bị hủy. Tự động giải phóng khi hết phạm vi sử dụng Không tự động giải phóng. Lập trình viên phải lo việc này. 25 Cấp phát biến động Không có tên, chỉ có địa chỉ dùng biến con trỏ để lưu địa chỉ. Cú pháp: Biế t ỏ Kiể HIENLTH, C++ - 2010 n-con- r = new u; Biến-con-trỏ = new Kiểu[số phần tử]; Ví dụ: int* p = new int; double* pd = new double[10]; 26 Hủy biến động Thông qua biến con trỏ lưu địa chỉ của biến động. Cú pháp: delete biến-con-trỏ; ế HIENLTH, C++ - 2010 delete [] bi n-con-trỏ; Ví dụ: delete p; delete [] pd; 27 Câu hỏi và thảo luận HIENLTH, C++ - 2010 28
File đính kèm:
- Slide bài giảng Lập trình C++ - Lương Trần Hy Hiến - Con trỏ.pdf