19
Tin Học Cơ Sở 4 Con trỏ

BaiGiang06 ConTro

Embed Size (px)

Citation preview

Page 1: BaiGiang06 ConTro

Tin Học Cơ Sở 4

Con trỏ

Page 2: BaiGiang06 ConTro

2

Nô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

Lê Nguyên Khôi

Page 3: BaiGiang06 ConTro

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ỏ:– 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

Lê Nguyên Khôi 3

Page 4: BaiGiang06 ConTro

Biế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,…

Lê Nguyên Khôi 4

Page 5: BaiGiang06 ConTro

Biế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

Lê Nguyên Khôi 5

Page 6: BaiGiang06 ConTro

Khai 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

• int *p1, *p2, v1, v2;– p1, p2 là con trỏ chỉ đến biến kiểu int– v1, v2 là biến kiểu int

Lê Nguyên Khôi 6

Page 7: BaiGiang06 ConTro

Khai báo Con Trỏ trong C

Lê Nguyên Khôi 7

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;

Page 8: BaiGiang06 ConTro

Toá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.

Lê Nguyên Khôi 8

0x91A2

0x1132

char g = 'z';

int main(){

char c = 'a';char *p;p = &c;p = &g;return 0;

}

char g = 'z';

int main(){

char c = 'a';char *p;p = &c;p = &g;return 0;

}

p c'a'

0x1132

p g

'z'0x91A2

Page 9: BaiGiang06 ConTro

Toán tử *• *: toán tử truy xuất giá trị của vùng nhớ được quản lý

bởi con trỏ.

Lê Nguyên Khôi 9

'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;

}

az

az

xuất giá trị tại vùng nhớ do p đang quản lý

0x91A2

0x1132

p c

0x1132

p g

0x91A2

Page 10: BaiGiang06 ConTro

Truyền tham số địa chỉ

Lê Nguyên Khôi 10

#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));

}

Page 11: BaiGiang06 ConTro

Truyền tham số giá trị

Lê Nguyên Khôi 11

#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);

}

Page 12: BaiGiang06 ConTro

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ệ.

Lê Nguyên Khôi 12

#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);return 0;

}

#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);return 0;

}

Page 13: BaiGiang06 ConTro

Toá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

Lê Nguyên Khôi 13

Page 14: BaiGiang06 ConTro

Toá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:

Lê Nguyên Khôi 14

0x15A4

0x15A0int 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;

p i10

0x15A014

q j

0x15A414

0x15A414

0x15A0int 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;

p i10

0x15A0q j

0x15A4

0x15A4

Page 15: BaiGiang06 ConTro

Luyện tập – Điền vào ô trống

Lê Nguyên Khôi 15

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;}

10i0x2100

14j0x2104

?k0x1208

0x2100p0x120B

q0x1210

0x2104

11

0x2108

14

Page 16: BaiGiang06 ConTro

Con 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.

Lê Nguyên Khôi 16

#include <stdio.h>int main(){

int a[10] = {1, 3, 4, 2, 0};int *p;p = a; //a = p: saiprintf(“0x%04X %i 0x%04X %i\n“,

a, a[0], p, *p);return 0;

}

#include <stdio.h>int main(){

int a[10] = {1, 3, 4, 2, 0};int *p;p = a; //a = p: saiprintf(“0x%04X %i 0x%04X %i\n“,

a, a[0], p, *p);return 0;

}

Page 17: BaiGiang06 ConTro

Toán tử + với số nguyên

Lê Nguyên Khôi 17

3344

0x15A20x15A2

#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;

}

11

55

22

00

aa

……

0x15A0

pp0x16B2

Page 18: BaiGiang06 ConTro

Con Trỏ - Luyện tập

Lê Nguyên Khôi 18

#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 23 11 91 3

2 23 11 91 3

Page 19: BaiGiang06 ConTro

Cấ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.

Lê Nguyên Khôi 19

#include <stdio.h>int main(){

int *p = (int*) malloc (sizeof(int) * 10);p[0] = 1;p[3] = -7;free(p);return 0;

}

#include <stdio.h>int main(){

int *p = (int*) malloc (sizeof(int) * 10);p[0] = 1;p[3] = -7;free(p);return 0;

}