Cú pháp và cách sử dụng toán tử điều kiện trong C++
Toán tử điều kiện có tên tiếng Anh là Conditional Operator. Được dùng để thay thế...
Kết quả sẽ mở trong tab mới, giới hạn trong website này.
Truy cập nhanh
Tìm kiếm gần đây
Trong C++, có một khái niệm rất hay nhưng khá khó hiểu khi mới lập trình là con trỏ (pointer). Để tìm hiểu về con trỏ, các bạn cần nắm vững về bộ nhớ của biến trong lập trình. Các bạn có thể đọc lại bài Hiểu rõ về bộ nhớ của biến trong C++. […]
Trong C++, có một khái niệm rất hay nhưng khá khó hiểu khi mới lập trình là con trỏ (pointer). Để tìm hiểu về con trỏ, các bạn cần nắm vững về bộ nhớ của biến trong lập trình. Các bạn có thể đọc lại bài Hiểu rõ về bộ nhớ của biến trong C++.
Bộ nhớ RAM chứa rất nhiều ô nhớ, mỗi ô nhớ có kích thước 1 byte.
Mỗi ô nhớ có địa chỉ duy nhất và địa chỉ này được đánh số từ 0 trở đi. Nếu CPU 32 bit thì có 2^32 địa chỉ có thể đánh cho các ô nhớ trong RAM.
Khi khai báo biến, trình biên dịch dành riêng một vùng nhớ với địa chỉ duy nhất để lưu biến. Trình biên dịch có nhiệm vụ liên kết địa chỉ ô nhớ đó với tên biến. Khi gọi tên biến, nó sẽ truy xuất tự động đến ô nhớ đã liên kết với tên biến để lấy dữ liệu. Các bạn phải luôn phân biệt giữa địa chỉ bộ nhớ và dữ liệu được lưu trong đó.
Có thể lấy địa chỉ của một biến bằng cách sử dụng toán tử &.
int a;
cout << "Address of a: " << &a << endl;
Address of a: 00F6FDFCĐịa chỉ của biến bản chất cũng là một con số thường được biểu diễn ở hệ cơ số 16. Ta có thể sử dụng con trỏ (pointer) để lưu địa chỉ của các biến.
Trong ngôn ngữ C++, con trỏ (pointer) là những biến lưu trữ địa chỉ bộ nhớ của những biến khác.
Trong hình trên, biến var lưu giá trị 5 có địa chỉ là 0x61ff08. Biến pointVar là biến con trỏ, lưu địa chỉ của biến var (trỏ đến vùng nhớ của biến var), tức là nó lưu giá trị 0x61ff08.
<kiểu dữ liệu> *<tên biến con trỏ>;
Ví dụ:
char *ch1, *ch2;
int *p1, p2;
ch1 và ch2 là biến con trỏ, trỏ tới vùng nhớ kiểu char (1 byte). p1 là biến con trỏ, trỏ tới vùng nhớ kiểu int (4 bytes), còn p2 là biến kiểu int bình thường.
Một biến bất kỳ phải xác định 2 thứ: địa chỉ của biến và giá trị của biến. Biến con trỏ cũng thế.
Khi mới khai báo, biến con trỏ được đặt ở địa chỉ nào đó (không biết trước), chứa giá trị là một địa chỉ không xác định hoặc địa chỉ 0xCCCCCCCC – là địa chỉ đặc biệt, cho biết con trỏ chưa được khởi tạo. Sử dụng toán tử & để đặt địa chỉ của một biến vào con trỏ.
Cú pháp: <tên biến con trỏ> = &<tên biến>;
Ví dụ:
int a, b;
int *pa, *pb;
pa = &a;
pb = &b;
Con trỏ NULL là con trỏ lưu địa chỉ 0x00000000. Tức địa chỉ bộ nhớ 0, có ý nghĩa đặc biệt, cho biết con trỏ không trỏ vào đâu cả.
int *p2;//con trỏ chưa khởi tạo, vẫn trỏ đến một vùng nhớ nào đó không xác định
int *p3 = NULL;//con trỏ null không trỏ đến vùng nhớ nào
Ví dụ có các khai báo:
int a = 5;
int *pa = &a;
Nắm rõ quy tắc sau: *pa và a đều chỉ giá trị của biến a, pa và &a đều chỉ địa chỉ của biến a, &pa là lấy địa chỉ của biến con trỏ pa.
#include <iostream>
using namespace std;
int main() {
int a = 5;
int *pa;
pa = &a;
//Dia chi
cout<<"Gia tri cua bien con tro pa la dia chi cua bien a:"<<pa<<endl;
cout<<"Dia chi cua bien a ma bien con tro pa tro den:"<<&a<<endl;
//Gia tri
cout<<"Gia tri vung nho ma bien con tro pa tro den:"<<*pa<<endl;
cout<<"Gia tri cua bien a ma bien con tro pa tro den:"<<a<<endl;
//Dia chi bien con tro
cout<<"Dia chi cua bien con tro pa:"<<&pa<<endl;
system("pause");
}
Gia tri cua bien con tro pa la dia chi cua bien a:00AFF948
Dia chi cua bien a ma bien con tro pa tro den:00AFF948
Gia tri vung nho ma bien con tro pa tro den:5
Gia tri cua bien a ma bien con tro pa tro den:5
Dia chi cua bien con tro pa:00AFF93C
Ví dụ các khai báo con trỏ sau:
char *p1;
int *p2;
float *p3;
double *p4;
Kích thước của các biến con trỏ có khác nhau không? Con trỏ chỉ lưu địa chỉ nên kích thước của mọi con trỏ là như nhau. Kích thước này phụ thuộc vào môi trường hệ thống máy tính:
#include <iostream>
using namespace std;
int main() {
char *p1;
int *p2;
float *p3;
double *p4;
cout<<"Size of char type pointer:"<<sizeof(char *)<<" bytes" <<endl;
cout<<"Size of int type pointer:"<<sizeof(int *)<<" bytes" <<endl;
cout<<"Size of float type pointer:"<<sizeof(float *)<<" bytes" <<endl;
cout<<"Size of double type pointer:"<<sizeof(double *)<<" bytes" <<endl;
system("pause");
}
Size of char type pointer:8 bytes
Size of int type pointer:8 bytes
Size of float type pointer:8 bytes
Size of double type pointer:8 bytes
Chữ NULL phải viết hoa, viết thường null sẽ bị lỗi.
int *p1 = NULL;//đúng
int *p2 = null;//lỗi
Kết quả tính toán có thể sẽ phát sinh những lỗi không lường trước được nếu chưa khởi tạo con trỏ.
int a = 5, *pa;
pa = &a;//được khởi tạo
int *pb;//phải khởi tạo
int var, *varPoint;
// lỗi
// varPoint là địa chỉ nhưng var không phải địa chỉ
varPoint = var;
// lỗi
// &var là địa chỉ
// *varPoint là giá trị được lưu trữ trong var
*varPoint = &var;
// đúng
// varPoint là địa chỉ và &var cũng là địa chỉ
varPoint = &var;
// đúng
// *varPoint và var đều là giá trị
*varPoint = var;
Xem ví dụ sau:
#include <iostream>
using namespace std;
int main() {
int *pa;
int a=5;
pa=&a;//pa lưu địa chỉ của biến a
*pa=100;//thay đổi giá trị trong vùng nhớ mà pa lưu trữ
cout<<"Gia tri cua a:"<<a;//giá trị lưu trong a cũng thay đổi
system("pause");
}
Gia tri cua a:100Tên biến chỉ đại diện cho vùng nhớ, có thể truy xuất hoặc thay đổi giá trị trong vùng nhớ đó. Do đó, khi giá trị trong vùng nhớ thay đổi thì giá trị truy xuất được thông qua tên biến cũng thay đổi.
Con trỏ là khái niệm quan trọng và khó nhất trong C/C++. Mức độ thành thạo C/C++ được đánh giá qua mức độ sử dụng con trỏ. Do đó, các bạn cố gắng hiểu rõ và luyện tập cách sử dụng con trỏ nhé.
Nếu có bất cứ thắc mắc nào, các bạn cứ comment bên dưới, mình sẽ giải đáp cho các bạn.