Giới thiệu về Con Trỏ• Định nghĩa Con trỏ: – 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 – Chứa địa chỉ của biến mang giá trị cụ thể • Mục đích Con trỏ: – Tru
Trang 1Tin Học Cơ Sở 4
Con trỏ
Trang 2Nội Dung
• Khai báo
• Các toán tử & , * , = , +
• Nhắc lại về truyền tham số địa chỉ
• Con trỏ & mảng
• Cấp phát vùng nhớ động
Trang 3Giới thiệu về Con Trỏ
• Định nghĩa Con trỏ:
– 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
– Chứa địa chỉ của biến mang giá trị cụ thể
• Mục đích Con trỏ:
– Truyền tham số kiểu địa chỉ
– Biểu diễn các kiểu & cấu trúc dữ liệu động
– Liên quan chặt chẽ đến mảng & xâu
• Con trỏ đã được sử dụng trong hàm scanf
Trang 4Biến Con Trỏ
• Con trỏ là kiểu dữ liệu
– Kiểu con trỏ phải được định nghĩa trên một kiểu cơ
sở đã được định nghĩa trước đó.
typedef kiểucơsở * Tênkiểu;
typedef int * IntPointer;
// IntPointer là kiểu con trỏ - địa chỉ vùng nhớ kiểu int
– Có thể dùng biến để lưu trữ con trỏ
– Không phải kiểu int , double ,…
•Là con trỏ chỉ đến biến kiểu dữ liệu int, double,…
Trang 5Biến Con Trỏ - Ví dụ
int x;
int *p;
IntPointer p1;
– p và p1 được khai báo là con trỏ chỉ đến kiểu int
– p và p1 là biến kiểu int*
– p và p1 có thể dùng để lưu địa chỉ của biến kiểu int
–Có thể sử dụng p và p1 để lưu địa chỉ của x
Trang 6Khai báo biến Con Trỏ
• Khai báo biến con trỏ giống các biến kiểu
dữ liệu khác:
– Thêm toán tử * vào trước biến
– Tạo ra con trỏ chỉ đến kiểu dữ liệu khai báo
• Toán tử * bắt buộc phải ở trước biến
– p1 , p2 là con trỏ chỉ đến biến kiểu int
– v1 , v2 là biến kiểu int
Trang 7Khai báo Con Trỏ trong C
int *pi;
long int *p;
float *pf;
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;
int *pi;
long int *p;
float *pf;
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;
Trang 8Toán tử &
• & : toán tử lấy (trả về) địa chỉ của 1 biến.
• Đị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.
0x91A2
0x1132
char g = 'z';
int main()
{
char c = 'a';
char *p;
p = &c;
p = &g;
char g = 'z';
int main()
{
char c = 'a';
char *p;
p = &c;
p = &g;
return 0;
'a' 0x1132
'z' 0x91A2
Trang 9Toán tử *
• * : toán tử truy xuất giá trị của vùng nhớ được quản lý
bởi con trỏ.
'a'
'z'
#include <stdio.h>
char g = 'z';
int main()
{
char c = 'a';
char *p;
p = &c;
printf("%c\n", *p);
p = &g;
printf("%c\n", *p);
return 0;
#include <stdio.h>
char g = 'z';
int main()
{
char c = 'a';
char *p;
p = &c;
printf("%c\n", *p);
p = &g;
printf("%c\n", *p);
return 0;
a z
a z
xuất giá trị tại vùng nhớ
do p đang quản lý 0x91A2
0x1132
0x1132
0x91A2
Trang 10Truyền tham số địa chỉ
#include <stdio.h>
void ThayDoiTruyenDiaChi(int *v);
int main()
{
int var = 5;
ThayDoiTruyenDiaChi(&var);
printf("main: var = %i\n", var);
return 0;
}
void ThayDoiTruyenDiaChi(int *v)
{
(*v) *= 100;
printf(“ham: *v = %i\n", (*v));
#include <stdio.h>
void ThayDoiTruyenDiaChi(int *v);
int main()
{
int var = 5;
ThayDoiTruyenDiaChi(&var);
printf("main: var = %i\n", var);
return 0;
}
void ThayDoiTruyenDiaChi(int *v)
{
(*v) *= 100;
printf(“ham: *v = %i\n", (*v));
Trang 11Truyền tham số giá trị
#include <stdio.h>
void ThayDoiTruyenGiaTri(int v);
int main()
{
int var = 5;
ThayDoiTruyenGiaTri(var);
printf("main: var = %i\n", var);
return 0;
}
void ThayDoiTruyenGiaTri(int v)
{
v *= 100;
printf(“ham: v = %i\n", v);
}
#include <stdio.h>
void ThayDoiTruyenGiaTri(int v);
int main()
{
int var = 5;
ThayDoiTruyenGiaTri(var);
printf("main: var = %i\n", var);
return 0;
}
void ThayDoiTruyenGiaTri(int v)
{
v *= 100;
printf(“ham: v = %i\n", v);
}
Trang 12Con 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ệ.
#include <stdio.h>
int main() {
int i = 13;
short *p = NULL;
if (p == NULL)
printf(“Con trỏ không hợp lệ!\n");
else
printf(“Giá trị : %hi\n", *p);
#include <stdio.h>
int main() {
int i = 13;
short *p = NULL;
if (p == NULL)
printf(“Con trỏ không hợp lệ!\n");
else
printf(“Giá trị : %hi\n", *p);
Trang 13Toán tử gán =
• Có thể gán giá trị cho biến con trỏ
int *p, *q;
p = q;
–Gán giá trị con trỏ cho con trỏ khác
–Cho p chỉ tới vùng nhớ mà q đang chỉ
• Không được nhầm lẫn với:
*p = *q;
–Gán giá trị mà q đang chỉ đến cho biến (vùng nhớ) mà p đang chỉ đến
Trang 14Toán tử gán = - Ví dụ
• Có sự khác biệt rất quan trọng khi thực hiện các phép gán:
và
0x15A4
0x15A0
int i = 10, j = 14;
int *p = &i;
int *q = &j;
*p = *q;
int i = 10, j = 14;
int *p = &i;
int *q = &j;
*p = *q;
10 0x15A0 14
0x15A4
14
0x15A0
int i = 10, j = 14;
int *p = &i;
int *q = &j;
int i = 10, j = 14;
int *p = &i;
int *q = &j;
10 0x15A0
0x15A4
Trang 15Luyện tập – Điền vào ô trống
int main(void)
{
int i = 10, j = 14, k;
int *p = &i;
int *q = &j;
*p += 1;
p = &k;
*p = *q;
p = q;
*p = i;
return 0;
}
int main(void)
{
int i = 10, j = 14, k;
int *p = &i;
int *q = &j;
*p += 1;
p = &k;
*p = *q;
p = q;
*p = i;
return 0;
}
10
i 0x2100
14
j 0x2104
?
k 0x1208
0x2100
p 0x120B
q 0x1210 0x2104
11
0x2108 14
Trang 16Con Trỏ & 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 bao giờ thay đổi.
• Biến con trỏ là địa chỉ động của một vùng nhớ, được xác định qua phép gán địa chỉ khi chương trình thực thi.
#include <stdio.h>
int main() {
int a[10] = {1, 3, 4, 2, 0};
int *p;
p = a; //a = p: sai
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
#include <stdio.h>
int main() {
int a[10] = {1, 3, 4, 2, 0};
int *p;
p = a; //a = p: sai
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
Trang 17Toán tử + với số nguyên
3
0x15A2
#include <stdio.h>
int main()
{
short a[10] = {1, 3, 5, 2, 0};
short *p = a;
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
p ++;
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
(*p) ++;
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
return 0;
#include <stdio.h>
int main()
{
short a[10] = {1, 3, 5, 2, 0};
short *p = a;
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
p ++;
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
(*p) ++;
printf(“0x%04X %i 0x%04X %i\n“,
a, a[0], p, *p);
return 0;
1
5 2 0 a
… 0x15A0
p 0x16B2
Trang 18Con Trỏ - Luyện tập
#include <stdio.h>
int main()
{
int a[10] = {2, 3, 5, 1, 4, 7, 0};
int *p = a;
printf(“%i %i\n“, a[0], *p);
p ++;
printf(“%i %i\n“, *p, p[2]);
p ++; a[2] = 9;
printf(“%i %i\n“, p[1], *p);
p -= 2;
printf(“%i %i\n”, p[3], p[1]);
return 0;
#include <stdio.h>
int main()
{
int a[10] = {2, 3, 5, 1, 4, 7, 0};
int *p = a;
printf(“%i %i\n“, a[0], *p);
p ++;
printf(“%i %i\n“, *p, p[2]);
p ++; a[2] = 9;
printf(“%i %i\n“, p[1], *p);
p -= 2;
printf(“%i %i\n”, p[3], p[1]);
return 0;
2 2
3 1
1 9
1 3
2 2
3 1
1 9
1 3
Trang 19Cấp phát vùng nhớ động
• Có thể chỉ định vùng mới cho 1 con trỏ quản lý bằng các lệnh hàm malloc.
• Vùng nhớ do lập trình viên chỉ định phải được giải phóng bằng lệnh free.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int*) malloc (sizeof(int) * 10); p[0] = 1;
p[3] = -7;
free(p);
return 0;
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int*) malloc (sizeof(int) * 10);
p[0] = 1;
p[3] = -7;
free(p);
return 0;