Pointers-Basic
Căn bản về Pointers
1. Biến được và bộ nhớ máy tính.
Trước khi nói về Pointers chúng ta sẽ tìm hiểu về memory và memory được tổ chức như thế nào trong máy tính. Ở đây chúng ta nói về RAM (Random Access Memory), để dễ dàng quản lý và sử dụng, OS (Hệ điều hành) sử dụng ram ảo (virtual memory) thay vì ram vậy lý thật. Memory trong máy tính được tạo thành từ các bytes được xắp xếp theo trình tự. Mỗi bytes thì được đánh chỉ mục (index) ta gọi là địa chỉ (address). Địa chỉ mỗi byte bắt đầu bằng 0 và kết thúc không vượt quá kích thước của memory. Giả sử chúng ta có 64MB RAM thì địa chỉ các bytes sẽ từ 0 đến .
Khi chúng ta khai báo một biến thì trình biên dịch (compiler) phải dành riêng không gian cho nó. Kiểu dữ liệu phải được biết để trình biên dịch biết cần kích thước bao nhiêu để cấp phát. Giả sử chúng ta khai báo int x = 4;
Lúc này, compiler sẽ tìm trong bộ nhớ chính (RAM) một vùng trống đủ lớn để lưu trữ một giá trị kiểu int. Trên hầu hết các hệ thống 16-bit, một biến int chiếm 2 byte; còn trên hệ thống 32-bit hoặc 64-bit hiện đại, một biến int thường chiếm 4 byte. Sau khi vùng nhớ này được cấp phát, địa chỉ của byte đ ầu tiên trong vùng nhớ đó sẽ được coi là địa chỉ của biến x  và giá trị 4 sẽ gán với địa chỉ này như hình minh họa bên dưới.

Hình 1 : Biến được khởi tạo trong memory
2. Truy cập địa chỉ của biến
Trong ngôn ngữ lập trình C/C++ để truy cập địa chỉ của biến ta có thể dùng ký hiệu & (address operator) ngay trước tên biến.
#include<stdio.h>
int main() {
  int x = 30;
  printf("Value of x %d , , Address of x,= %u\n", x, & x);
  return 0;
}
Output: Value of x = 30, Address of x = 65524
ví dụ : &123 và &(x + i) : not valid
3. Biến con trỏ (Pointers).
Con trỏ là một biến như một loại biến bình thường trong ngôn ngữ lập trình chỉ có điều đặc biệt là nó lưu trữ địa chỉ của memory. Nó cũng có tên, cũng được khai báo và cũng chiếm vùng nhớ ở trong RAM. Nó được gọi là con trỏ vì nó trỏ đến địa chỉ cụ thể trong bộ nhớ bằng cách lưu trữ địa chỉ vùng nhớ đó.
Ta khai báo một biến Pointers như sau data_type int *ptr , ta dùng ký hiệu * trước tên biến, đọc là biến con trỏ ptr kiểu data_type.
#include<stdio.h>
int main() {
  int *iptr; // khai báo biến pointer iptr kiểu dữ liệu int
  double *fptr; // khai báo biến pointer fptr kiểu dữ liệu double
  char *cptr; // khai báo biến pointer cptr kiểu dữ liệu character
  printf("Size of int*     = %zu\n", sizeof(int*));
  printf("Size of char*    = %zu\n", sizeof(char*));
  printf("Size of double*  = %zu\n", sizeof(double*));
  return 0;
}
  Size of int*     = 8
  Size of char*    = 8
  Size of double*  = 8
Compiler thường sử dụng 8 (hoặc 4 byte tùy thuộc vào kiến trúc máy tính) byte để lưu trữ biến con trỏ cho dù biến con trỏ đó là loại gì.
4. Gán địa chỉ đến biến Pointers.
Khi chúng ta khai báo một biến con trỏ nó sẽ có một giá trị rác (garbage value) nào đó, nó có thể trỏ đến bất kỳ vùng nhớ nào trong memory. Vì vậy chúng ta nên gắn giá trị địa chỉ cụ thể khi chạy chương trình. Việc sử dụng con trỏ chưa được gán giá trị có thể dẫn đến kết quả không dự đoán trước được và cũng có thể làm sập(crash) chương trình. Để gán giá trị cho con trỏ ta có thể làm như sau.
#include<stdio.h>
int main() {
  int x = 10;
  double y = 20.5;
  int *iptr; 
  double *dptr;
  
  iptr = &x;
  dptr = &y;
  return 0;
}
Để gán giá trị cho biến pointers ta dùng & để lấy địa chỉ của biến .

Hình 2 : Gắn giá trị địa chỉ cho biến Pointers
Chúng ta có thể gán hằng số 0 cho một con trỏ thuộc bất kỳ kiểu nào. Hằng số ký hiệu NULL được định nghĩa trong thư viện stdio.h,
biểu thị giá trị zero. Việc gán NULL cho một con trỏ đảm bảo rằng nó không trỏ đến bất kỳ vị trí nào trong memory ptr = NULL .